• 环境:FreeRTOS & LwIP 2.2.0
  • 文章中的所有参数检测的断言代码都删除以使代码更清晰

LwIP通过调用tcpip_init来初始化TCPIP协议栈,函数如下所示,函数中代码的含义见注释:

static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
static sys_mbox_t tcpip_mbox;
sys_mutex_t lock_tcpip_core;void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{/* 初始化LwIP */lwip_init();/* 初始化完毕后调用的回调函数,可传NULL,在tcpip_thread开头调用 */tcpip_init_done = initfunc;tcpip_init_done_arg = arg;/* 创建message box,实际上是FreeRTOS的Queue* 每个项目大小为一个指针的大小(4B),队列长度为TCPIP_MBOX_SIZE */if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {LWIP_ASSERT("failed to create tcpip_thread mbox", 0);}#if LWIP_TCPIP_CORE_LOCKING/* 创建互斥锁:用户可以通过这个锁在代码中实现LwIP的一些操作,而不需要在tcpip_thread的callback中实现 */if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {LWIP_ASSERT("failed to create lock_tcpip_core", 0);}#endif /* LWIP_TCPIP_CORE_LOCKING *//* 创建FreeRTOS任务tcpip_thread */sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}

其中lwip_init函数内容如下(各个初始化需要打开相应的宏定义,这里略去#ifdef...#endif的宏定义以方便阅读代码):

void lwip_init(void)
{/* 统计模块初始化,这里只是初始化lwip_stats.mem.name为MEM */stats_init();/* 带操作系统时的初始化:函数中暂时没有内容 */sys_init();/* 初始化内存堆的起始地址、结束地址以及空闲列表 */mem_init();/* 初始化LwIP内存池 */memp_init();/* 初始化pbuf:函数中暂时没有内容 */pbuf_init();/* 初始化netif:主要是环回的ip,网关,子网掩码以及netif的添加和配置 */netif_init();/* 兼容老版本:函数中暂时没有内容 */ip_init();/* 兼容老版本:函数中暂时没有内容 */etharp_init();/* 兼容老版本:函数中暂时没有内容 */raw_init();/* 初始化UDP端口号(随机分配),范围:0xc000~0xffff */udp_init();/* 初始化TCP端口号(随机分配),范围:0xc000~0xffff */tcp_init();/* 初始化组播IP */igmp_init();/* 初始化DNS解析:设置UDP PCB并配置默认服务器 */dns_init();/* 初始化PPP:根据配置分配相关的结构体内存和初始化魔术字(PPP连接需要用到) */ppp_init();/* 初始化软件定时器 */sys_timeouts_init();
}

最后,可以看到tcpip_init最终调用sys_thread_new创建了一个tcpip_thread任务,看看它做了什么:

static void tcpip_thread(void *arg)
{struct tcpip_msg *msg;/* 上锁 */LOCK_TCPIP_CORE();/* 调用前面设置的回调函数 */if (tcpip_init_done != NULL) {tcpip_init_done(tcpip_init_done_arg);}while (1) {/* wait for a message, timeouts are processed while waiting */TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);if (msg == NULL) {LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));LWIP_ASSERT("tcpip_thread: invalid message", 0);continue;}tcpip_thread_handle_msg(msg);}
}

可见,最后是调用TCPIP_MBOX_FETCH来等待消息,这个函数中还有定时器的检查,具体解释参考:LwIP源码分析(1):软件定时器。

static void
tcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
{u32_t sleeptime, res;again:LWIP_ASSERT_CORE_LOCKED();sleeptime = sys_timeouts_sleeptime();if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {UNLOCK_TCPIP_CORE();sys_arch_mbox_fetch(mbox, msg, 0);LOCK_TCPIP_CORE();return;} else if (sleeptime == 0) {sys_check_timeouts();/* We try again to fetch a message from the mbox. */goto again;}UNLOCK_TCPIP_CORE();res = sys_arch_mbox_fetch(mbox, msg, sleeptime);LOCK_TCPIP_CORE();if (res == SYS_ARCH_TIMEOUT) {/* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurredbefore a message could be fetched. */sys_check_timeouts();/* We try again to fetch a message from the mbox. */goto again;}
}

对于这边的互斥锁,tcpip_thread一上来就调用LOCK_TCPIP_CORE上锁,在TCPIP_MBOX_FETCH中等待消息队列阻塞时释放这个锁,等待完这个队列,无论有没有消息到来,sys_arch_mbox_fetch返回后就立即上锁,因为在此期间tcpip_thread已经阻塞死等,此时用户可以调用部分LwIP内核函数。

对于消息处理函数tcpip_thread_handle_msg(msg)相关的结构体和实现需要在了解TCP/IP原理之后进行分析,这样知道在哪里在何时会往这个mbox发送消息,我们才能知道每个消息的定义,不同的消息需要执行什么操作。后续循序渐进地分析完LwIP相关代码后,我会写一个博客来分析,这里暂不讨论。

LwIP源码分析(2):tcpip_init和tcpip_thread函数分析相关推荐

  1. LWIP源码分析——ip4.c

    LWIP源码分析--ip4.c ipv4是IP栈中重要的一部分,实现功能使用了上千行代码,分析起来可能会稍显复杂,这部分采用的分析的思路是,重点思想总结部分放在前面,剩下的结合代码穿插分析 1.ipv ...

  2. 【Android 10 源码】healthd 模块 HAL 2.0 分析

    Android 9 引入了从 health@1.0 HAL 升级的主要版本 android.hardware.health HAL 2.0.这一新 HAL 具有以下优势: 框架代码和供应商代码之间的区 ...

  3. vue+django 微博舆情系统源码、深度学习+舆情扩散消失分析、舆情紧急等级、属地分析、按话题、情感预测、话题评论获取、提取观点、正面负面舆情、按区域检测舆情

    项目背景 315又马上要到了,现在有开始对食品安全话题的关注地提升了,因此,本文系统对微博的食品安全话题进行分析,有如下的功能 1.展示当前食品安全事件相关的热点信息以及提供根据食品关键词,食品安全类 ...

  4. Postgresql源码(82)SPI模块拆解分析一:执行简单SQL获取结果

    相关 <Postgresql源码(76)执行器专用元组格式TupleTableSlot> <Postgresql源码(82)SPI模块拆解分析一:执行简单SQL获取结果> &l ...

  5. 抖音seo优化源码搭建/搜索排名系统,技术理论分析搭建中。

    抖音seo系统源码SaaS+源码私有化部署搭建,抖音seo源码,抖音seo系统源码,抖音seo系统搭建部署,抖音已经成为了当今最为流行的短视频平台之一,拥有着庞大的用户群体和海量的视频资源.对于一些商 ...

  6. [附源码]计算机毕业设计JAVA学生考试成绩分析系统

    [附源码]计算机毕业设计JAVA学生考试成绩分析系统 项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(In ...

  7. Postgresql源码(69)常规锁细节分析

    相关: <Postgresql源码(40)Latch的原理分析和应用场景> <Postgresql源码(67)LWLock锁的内存结构与初始化> <Postgresql源 ...

  8. 4、Eureka 源码解析 之 Eureka Client 启动原理分析

    在前面的一篇文章 3.Eureka 源码解析 之 Eureka Server 启动原理分析当中我们分析了一下 Eureka Server 的启动.在集群环境下 Eureka Server 相互之前需要 ...

  9. 抖音SEO优化源码,搜索排名系统,技术理论分析,抖音矩阵,抖音seo系统。

    前言:抖音SEO优化源码,搜索排名系统,技术理论分析,抖音矩阵,抖音seo系统.抖音seo矩阵系统底层框架上支持了ai视频混剪,视频产出,视频AI制作,多账号多平台矩阵,视频一键内部分发,站内实现搜索 ...

最新文章

  1. NOIP2012-摆花
  2. 学好人工智能,其实不难,从以下几点开始
  3. ABP 重写主键ID
  4. Unity Time的使用
  5. SAP Spartacus B2B table的配置信息从哪里来?
  6. 学习笔记~~~~~python基础
  7. 说说C#的async和await
  8. Luogu P2664 树上游戏 dfs+树上统计
  9. creo扫描选择多条链作为轨迹_Proe/Creo曲面造型·蓝牙耳机纹理曲面纹理
  10. 深度学习怎么入门?零基础快速入门深度学习
  11. 在线图片尺寸怎么修改?图片在线修改尺寸大小方法
  12. mysql获取今天的最后一秒_Oracle取得当天0时0分0秒和23时59分59秒
  13. Redis生成自增流水号,每日清零
  14. 百万钱包借款时填资料一直显示服务器异常,百万钱包有连续放款失败,然后突然推过的吗?我已经失败四五...
  15. threejs粒子效果
  16. 《Flask Web开发:基于Python的Web应用开发实战》笔记(原创)
  17. vue登录页面实现记住密码的操作
  18. 班得瑞轻音乐全集[下载]
  19. hbuilder怎么做登录界面_HBuilder如何安装和使用?(教程)
  20. linux计划任务如何关闭程序,Linux进程控制和计划任务管理

热门文章

  1. Jx_Python基础库入门_2: 基本数据类型
  2. 百度统计搜索词是广告怎么办?建议设置过滤规则排除
  3. 【Bug】python requests发起请求,报“Max retries exceeded with url”
  4. Max retries exceeded with url问题解决
  5. testng执行参数_TestNG参数化测试
  6. 超融合一体流式引擎,打造分布式数据库新纪元
  7. 让视频丝滑流畅——N/A通用补帧傻瓜解决方案
  8. 拉黑技巧/幻隐网络科技
  9. PCB绘制与制作的总结
  10. 在SNAP中用sentinel-1数据制作DEM