代码片段与一些基本问题
参考: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)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
