代码片段与一些基本问题

参考:SINGER, ADAM B - PRACTICAL C DESIGN _ from programming to architecture-APRESS (2018)

需求搜集:尽管do your best,但实际上不可能预先收集所有需求。

数组或者list大小不应该硬编码,not be hard coded,可以用宏

undo和redo的操作,如何实现?undo , redo的stack大小没有限制

项目分析的点:1. 哪些问题需要注意? 2. 客户关注的点与我们关注的点差异?

分析与设计区分开来

分解问题的方式:自上而下,  自下而上

最底层的部分是各个功能的实现;自上而下的设计关注设计对象及其公共接口;自下而上的方式

将单个功能或对象级别object的方式组合,直到涵盖整个设计。

封装,内聚力,低耦合实现方式?

封装  --》 哪些部分是只有.c内部可见的?哪些接口是可以供外部使用的?

内聚力  --》 模块中哪些代码与函数适合放在一个.c中,而不是分散开的;内聚差的表现,不应该在一起的没有分开

功能耦合:一个模块的逻辑需要调用另外一个模块完成

数据耦合 --》  多个模块之间指向同一个数据,或者使用了指针

封装保护模块A免受模块B的内部实现更改的影响
低耦合保护模块A免受模块B接口的更改

设计模式与架构模式区分开

架构模式:多层架构体系multi-tiered architecture和MVC架构model-view-controller

命令调度程序:

命令调度程序的功能是
1.存储已知命令的集合,  CommandRepository
2.接收并解释对这些命令的请求, -->  commandDispatcher
3.调度命令请求(包括撤消功能)
和重做)               --》  CommandManager
4.执行实际操作(包括更新
计算器的状态)。

char *migrate_reason_names[MR_TYPES] = {
    "compaction",
    "memory_failure",
    "memory_hotplug",
    "syscall_or_cpuset",
    "mempolicy_mbind",
    "numa_misplaced",
    "cma",
};

const struct trace_print_flags pageflag_names[] = {
    __def_pageflag_names,
    {0, NULL}
};

const struct trace_print_flags gfpflag_names[] = {
    __def_gfpflag_names,
    {0, NULL}
};

 

嵌入式c的一些问题

https://github.com/vishnumotghare/Embedded-Systems-and-Linux-Interview-Questions

linux c的一些问题,偏向操作系统

https://github.com/Qiu-Ye/InterviewFAQ-Linux

https://github.com/zouxiaobo/interview_back_end/blob/master/03-Linux%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F.md      基础问法

https://github.com/zouxiaobo/interview_back_end/blob/master/04-%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C.md    linux网络基础问法

嵌入式的一些问题

https://github.com/nhtranngoc/embedded-interview-questions

https://github.com/egienvalue/Embedded_Interview/blob/master/EmbeddedTopics.md   内容涵盖范围比较多

https://github.com/lowkeyway/Embedded   关于iic的细看

https://github.com/arunkann/embedded_software     嵌入式的一些代码片段,.c文件

https://github.com/jtdykstra/embedded_interviews    嵌入式的一些代码片段,.c文件

https://github.com/yzhu798/CodingInterviewsNotes    一些面试题目

自动重传与超时重传

retransmission mode

在advt_ccb_act.cc中的avdt_ccb_ret_cmd函数

void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
  p_ccb->ret_count++;     --》 重传计数器
  if (p_ccb->ret_count == AVDT_RET_MAX) {   --》 重传达到最大次数
    /* command failed */
    p_ccb->ret_count = 0;
    tAVDT_CCB_EVT avdt_ccb_evt;
    avdt_ccb_evt.err_code = AVDT_ERR_TIMEOUT;
    avdt_ccb_cmd_fail(p_ccb, &avdt_ccb_evt);

    /* go to next queued command */
    avdt_ccb_snd_cmd(p_ccb, p_data);
  } else {
    /* if command pending and we're not congested and not sending a fragment */
    if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) &&
        (p_ccb->p_curr_cmd != NULL)) {
      /* make copy of message in p_curr_cmd and send it */
      BT_HDR* p_msg = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
      memcpy(p_msg, p_ccb->p_curr_cmd,
             (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset +
              p_ccb->p_curr_cmd->len));
      avdt_msg_send(p_ccb, p_msg);
    }

    /* restart ret timer */
    alarm_cancel(p_ccb->idle_ccb_timer);    --》 重启重传timer
    alarm_cancel(p_ccb->rsp_ccb_timer);
    uint64_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
    alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
                       avdt_ccb_ret_ccb_timer_timeout, p_ccb);    --》 timeout处理
  }
}

在avdt_api.cc中的timeout函数,例如avdt_ccb_ret_ccb_timer_timeout

 

http://blog.chinaunix.net/uid-30571370-id-5644672.html

https://www.cnblogs.com/kzang/articles/2582957.html

https://segmentfault.com/a/1190000017049539

https://www.cnblogs.com/ixxonline/archive/2011/09/10/2173292.html

https://www.cnblogs.com/lshs/p/6038527.html

 

在.git文件夹下的config包含src branch的链接

例如https://gitee.com/zhangheidan8421/vxWorks.git

D:\git\vxWorks\target\src\libc\string\strcpy.c   复制字符串

在string目录下,string的一些操作

https://aosp.tuna.tsinghua.edu.cn/platform/system/bt

直接git clone https://aosp.tuna.tsinghua.edu.cn/platform/system/bt

在a2d_api.h中定义函数指针

/* This is the callback to notify the result of the SDP discovery process. */
typedef void (tA2D_FIND_CBACK)(BOOLEAN found, tA2D_Service * p_service);     --》   void型的函数指针

在a2p_int.h中定义结构体,包含函数指针或者自定义结构体

/* Control block used by A2D_FindService(). */
typedef struct
{
    tA2D_FIND_CBACK     *p_cback;       /* pointer to application callback */       --》 函数指针
    tSDP_DISCOVERY_DB   *p_db;          /* pointer to discovery database */    --》  自定义结构体
    UINT16              service_uuid;   /* service UUID of search */
} tA2D_FIND_CB;

不同类型callback,返回不同,有void *类型的函数指针,有void的函数指针

例如alarm.h中的

// Prototype for the alarm callback function.
typedef void (*alarm_callback_t)(void *data);       --》  void *的函数指针

在alarm.c中,一个结构体中带有一个lock锁

struct alarm_t {
  // The lock is held while the callback for this alarm is being executed.
  // It allows us to release the coarse-grained monitor lock while a
  // potentially long-running callback is executing. |alarm_cancel| uses this
  // lock to provide a guarantee to its caller that the callback will not be
  // in progress when it returns.
  pthread_mutex_t callback_lock;      --》带有一个Lock,初始化一个Mutex
  period_ms_t creation_time;
  period_ms_t period;
  period_ms_t deadline;
  period_ms_t prev_deadline;    // Previous deadline - used for accounting of
                                // periodic timers
  bool is_periodic;
  fixed_queue_t *queue;         // The processing queue to add this alarm to     --》带有一个queue
  alarm_callback_t callback;    --》带有一个callback
  void *data;
  alarm_stats_t stats;
};

在bluetooth_gatt_interface.cpp中,定义了不同的callback

const btgatt_callbacks_t gatt_callbacks = {
  sizeof(btgatt_callbacks_t),
  &gatt_client_callbacks,
  &gatt_server_callbacks
};

在stack_manager.h中定义,函数指针结构体的应用场景-》 函数指针结构体用作接口,适用于不同的type对象操作相同

typedef struct {
  void (*init_stack)(void);     --》函数指针
  void (*start_up_stack_async)(void);
  void (*shut_down_stack_async)(void);
  void (*clean_up_stack)(void);

  bool (*get_stack_is_running)(void);
} stack_manager_t;

const stack_manager_t *stack_manager_get_interface();   --》定义一个接口函数,该函数只是在引用

一个已经定义好的函数指针,可以减少使用extern

该接口可以被其他.c中使用

在stack_manager.c中,   真实的接口函数为interface

static const stack_manager_t interface = {
  init_stack,
  start_up_stack_async,
  shut_down_stack_async,
  clean_up_stack,

  get_stack_is_running
};

const stack_manager_t *stack_manager_get_interface() {
  ensure_manager_initialized();
  return &interface;      --》  返回interface指针,可以在其他.c中使用;这样其他.c无法直接对这些接口操作
}

stack_manager_get_interface()该函数被哪些.c中使用?表示.c直接存在依赖关系

bluetooth.c,  btif_core.c, btif_profile_queue.c中

类似该写法,在btif_hf.c中的btif_hf_get_interface()中

在btif_hf_client.c中的btif_hf_client_get_interface()中

bluetooth.c中的get_profile_interface,这样在该.c中可以引用不同的interface接口

这里可以注意void *指针向其他类型的指针转换

在bdtool.c中,    const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);    --》  void*转换为sock对应的指针

 

对于p0版本的branch,

a2dp_codec_config.cc中的A2DP_GetEncoderInterface接口,

tA2DP_ENCODER_INTERFACE*为统一的接口,不同codec的接口统一使用     --》 函数指针结构体的应用场景

const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterface(
    const uint8_t* p_codec_info) {
  tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);

  LOG_VERBOSE("%s: codec_type = 0x%x", __func__, codec_type);

  switch (codec_type) {       --》  根据codec类型,决定使用哪个encoder
    case A2DP_MEDIA_CT_SBC:
      return A2DP_GetEncoderInterfaceSbc(p_codec_info);    
    case A2DP_MEDIA_CT_AAC:
      return A2DP_GetEncoderInterfaceAac(p_codec_info);
    case A2DP_MEDIA_CT_NON_A2DP:
      return A2DP_VendorGetEncoderInterface(p_codec_info);
    default:
      break;
  }

dispatch的用法,分发机制

例如packet_fragmenter.cc中,分发函数reassemble_and_dispatch

static const packet_fragmenter_t interface = {init, cleanup,

                                              fragment_and_dispatch,
                                              reassemble_and_dispatch};

不同profile都需要注册l2cap的方式

第2个参数为函数指针结构体,函数指针结构体用法,定义一系列callback  --》 函数指针结构体应用场景

使用register的目的是,完成callback与psm的绑定,实现过程如下:

#define AVCT_PSM 0x0017

Avct_api.cc (d:\git\bt_p0\stack\avct):  L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl,      --》 函数指针变换

--》到l2c_api.cc中,L2CA_Register函数,主要逻辑如下

uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
                       bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info) {
 

  tL2C_RCB* p_rcb;   --》L2c_int.h 中定义
  uint16_t vpsm = psm;   --》 暂时使用的,用于查询使用

  /* If registration block already there, just overwrite it */
  p_rcb = l2cu_find_rcb_by_psm(vpsm);   --》这里通过find查找到一个位置并赋值,在该函数中

说明   l2cu_find_rcb_by_psm(uint16_t psm) {    --》在rcb_pool池子中找是否有可用的,注意分配函数l2cu_allocate_rcb
  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];     --》 注意变量l2cb
  uint16_t xx;

  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);   --》  psm在用并且已经被分配了
  }

  /* If here, no match found */
  return (NULL);
}   --》 以上逻辑遵循了变量在本文件.cc中操作的原则,l2cb变量的属性不是直接被其他.c中文件操作,而是间接通过指针使用

  if (p_rcb == NULL) {
    p_rcb = l2cu_allocate_rcb(vpsm);     --》  分配L2cap的位置
    if (p_rcb == NULL) {
      L2CAP_TRACE_WARNING("L2CAP - no RCB available, PSM: 0x%04x  vPSM: 0x%04x",
                          psm, vpsm);
      return (0);
    }
  }

  p_rcb->log_packets = enable_snoop;
  p_rcb->api = *p_cb_info;    --》  这里完成了psm与callback操作的绑定
  p_rcb->real_psm = psm;

  return (vpsm);
}

Avct_api.cc (d:\git\bt_p0\stack\avct):  L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl,
Avdt_api.cc (d:\git\bt_p0\stack\avdt):  L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl,
Bnep_main.cc (d:\git\bt_p0\stack\bnep):  if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info, false /* enable_snoop */,
Gap_conn.cc (d:\git\bt_p0\stack\gap):    p_ccb->psm = L2CA_Register(psm, &conn.reg_info, false /* enable_snoop */,
Gatt_main.cc (d:\git\bt_p0\stack\gatt):  if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info,
Hidd_conn.cc (d:\git\bt_p0\stack\hid):  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info,
Hidd_conn.cc (d:\git\bt_p0\stack\hid):  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info,
Hidh_conn.cc (d:\git\bt_p0\stack\hid):  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info,
Hidh_conn.cc (d:\git\bt_p0\stack\hid):  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info,
Rfc_l2cap_if.cc (d:\git\bt_p0\stack\rfcomm):  L2CA_Register(BT_PSM_RFCOMM, p_l2c, true /* enable_snoop */, nullptr);
Sdp_main.cc (d:\git\bt_p0\stack\sdp):  if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */,

资源池pool的例子

定义的位置在l2c_int.h中

/* Define the L2CAP control structure
*/
typedef struct {

  tL2C_LCB lcb_pool[MAX_L2CAP_LINKS];    /* Link Control Block pool */    --》 资源池
  tL2C_CCB ccb_pool[MAX_L2CAP_CHANNELS]; /* Channel Control Block pool */
  tL2C_RCB rcb_pool[MAX_L2CAP_CLIENTS];  /* Registration info pool */

  tL2C_CCB* p_free_ccb_first; /* Pointer to first free CCB */
  tL2C_CCB* p_free_ccb_last;  /* Pointer to last  free CCB */

 
  tL2C_RCB ble_rcb_pool[BLE_MAX_L2CAP_CLIENTS]; /* Registration info pool */  --》 注册池

  tL2CA_ECHO_DATA_CB* p_echo_data_cb; /* Echo data callback */

} tL2C_CB;
 

参考使用写法L2c_utils.cc (d:\git\bt_p0\stack\l2cap)  

l2cu_allocate_rcb  --》 注册信息池分配

l2cu_allocate_ccb   --》 信道池分配

 

gatt定义的callback

在gatt_api.h中

/* discover result callback function */

typedef void(tGATT_DISC_RES_CB)(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
                                tGATT_DISC_RES* p_data);
 

函数指针结构体  tGATT_CBACK

在bta_gattc_act.cc中定义

static tGATT_CBACK bta_gattc_cl_cback = {bta_gattc_conn_cback,
                                         bta_gattc_cmpl_cback,
                                         bta_gattc_disc_res_cback,

变量bta_gattc_cl_cback使用位置,与app_uuid注册绑定  --》 GATT_Register(app_uuid, &bta_gattc_cl_cback)) == 0)

 

 

 

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部