TaterLi's LazyBlog

自言自语,不喜绕路,科学上网,远离天国.

@TaterLi3周前

01/29
11:16
技术控

LwIP 代码分析(netconn申请) – 第二集

之前udp的演示代码中,包含这些东西.

    struct netconn *udpconn;
    struct netbuf *udpbuf;
    struct netbuf *recv_udpbuf;
    ip_addr_t udpaddr;
    uint8_t udpdemo_buf[5] = {0xAA, 0x55, 0xFF, 0x5A, 0xA5};
    err_t err;
    err_t recv_err;

可以轻松推测,udpconn,udpbuf,recv_udpbuf都在代码里面肯定涉及到malloc类似的操作,不然没意义.

第一个函数,看名字就是新建连接块.

但是他又是一个define.

#define netconn_new(t)                  netconn_new_with_proto_and_callback(t, 0, NULL)

果然一进来就申请内存.

怎么申请的我先跳过,然后就看到他申请到了.

然后 把数据传递给lwip_netconn_do_newconn函数(通过msg变量),完成一个新的netconn创建,明显,他也会成功,才会返回成功.否则就是打印一堆错误信息,然后释放信号量,邮箱,和最初alloc得到的内存.

所以,总结起来,就是alloc内存,然后lwip_netconn_do_newconn处理就得到netconn了.

为什么要经历netconn_apimsg来调用lwip_netconn_do_newconn,跟进去看看,发现他还用tcpip_send_msg_wait_sem,看名字,wait sem,就是等待信号量,结果进去一看,是等待整个LwIP Core的锁,原来LwIP有两种等待方法,一种是独立的mbox,sem要用到的,就是独立锁的方式.后者每条线程申请一个独立锁,看起来可以增加并发量,前者直接锁定核心,看起来更低出错率.

千辛万苦的调用后,终于到了lwip_netconn_do_newconn,给我的参数是msg.由于msg->conn就是刚alloc到一块新内存,自然pcb是NULL的.628行自然可以进去.

为什么是判断tcp是NULL呢,我猜是因为只要其中一个NULL,其他都是NULL的,就抓一个来试试吧.然后就执行到pcb_new(总算是真正的新建了)

[其实是因为pcb是个联合体]

用udp_new_ip_type新建了一下,再看611行,如果任何一种包申请到了,IP包也会一并申请到.否则就出错了.只需要判断IP的PCB有没有就行,他们是联合体.

udp_new_ip_type里面最关键就是udp_new,其他什么都没实际意义,然后就是malloc,清零(难道lwip没实现calloc),设置TTL,返回,申请成功.

申请成功的内存.

申请到了还有一个关键的,调用udp_recv,还有一个函数叫recv_udp,这个函数的作用就是,当UDP收到数据时候,回调recv_udp,参数就是我们申请到的udpconn.

是不是略微懵逼,就被一个netconn_new这么搞来.其实说到底,这个netconn_new调用了不多的东西.

开始->netconn_new->netconn_alloc(给conn申请内存)->memp_malloc(给PCB申请内存)->设置一些属性->完成

 

LwIP 代码分析(netconn申请) – 第二集