关于函数内传递回调函数的疑问:status_cb与output_cb执行逻辑
关于PPP回调函数的常见疑问解答
首先得澄清一个关键误解:你看到的output_cb和status_cb不是"未传递参数的函数",而是函数指针——我们把函数的地址传给pppos_create,后续由lwIP的PPP栈在合适的时机自动调用这些函数,并传入对应的参数。
先看整理后的示例代码:
回调函数定义与主函数调用
static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { struct netif *pppif = ppp_netif(pcb); switch(err_code) { case PPPERR_NONE: { printf("status_cb: Connected\n"); printf(" our_ipaddr = %s\r\n", ipaddr_ntoa(&pppif->ip_addr)); printf(" his_ipaddr = %s\r\n", ipaddr_ntoa(&pppif->gw)); printf(" netmask = %s\r\n", ipaddr_ntoa(&pppif->netmask)); break; } case PPPERR_PARAM: { printf("status_cb: Invalid parameter\r\n"); break; } } } static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { return HAL_UART_Transmit_IT(&huart1, data, sizeof(data)); } int main(void) { ppp_pcb *ppp; struct netif ppp_netif; ppp = pppos_create(&ppp_netif, output_cb, status_cb, 0); }
pppos_create函数定义
ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { pppos_pcb *pppos; ppp_pcb *ppp; pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB); if (pppos == NULL) { return NULL; } ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); if (ppp == NULL) { LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); return NULL; } memset(pppos, 0, sizeof(pppos_pcb)); pppos->ppp = ppp; pppos->output_cb = output_cb; return ppp; }
问题1:未传入err_code参数时,status_cb会输出什么?
首先要明确:我们不会直接调用status_cb,这个函数是给lwIP的PPP栈用的回调函数。当PPP链路状态发生变化时(比如连接建立、参数错误),lwIP会自动调用status_cb,并传入对应的err_code参数。
如果真的出现err_code未被传入的极端情况(比如底层调用逻辑出错),err_code会是一个随机的垃圾值:
- 如果这个随机值恰好等于
PPPERR_NONE,会输出连接成功的信息及IP地址、网关、子网掩码; - 如果等于
PPPERR_PARAM,会输出"status_cb: Invalid parameter"; - 如果是其他值,因为你的switch没有default分支,函数会直接退出,不会输出任何内容。
但在正常的lwIP使用中,这种情况不会发生——PPP栈一定会正确传入err_code,对应不同的链路事件。
问题2:status_cb和output_cb何时、如何被执行?
这两个都是PPP栈的回调函数,执行时机和触发逻辑如下:
1. status_cb(链路状态回调)
- 执行时机:当PPP链路的状态发生变化时触发,比如:
- 连接成功建立(
PPPERR_NONE); - 检测到无效参数(
PPPERR_PARAM); - 其他链路错误(比如连接断开、认证失败等,你的代码里没处理这些case)。
- 连接成功建立(
- 执行逻辑:
在pppos_create中,你传入的status_cb被作为link_status_cb参数传给了ppp_new函数。lwIP的PPP核心模块会在链路状态变更时,通过内部的函数调用链,最终触发status_cb执行,并传入对应的ppp_pcb指针、错误码err_code和你传入的ctx(这里是0)。
2. output_cb(数据输出回调)
- 执行时机:当PPP栈需要向外发送PPP帧数据时触发,比如协商过程中的控制帧、业务数据帧。
- 执行逻辑:
pppos_create把你传入的output_cb保存到了pppos->output_cb中,同时指定了&pppos_callbacks作为PPP操作回调集合。当PPP栈需要发送数据时,会调用pppos_callbacks中的发送函数,这个函数内部会调用你提供的output_cb,传入ppp_pcb指针、待发送的数据指针data、数据长度len和ctx,最终通过你实现的UART中断发送函数把数据发出去。
内容的提问来源于stack exchange,提问作者Sarp Engin Daltaban
相关产品推荐
相关产品推荐

