大型网站团队人数今日nba比赛直播
关于 lwIP
多线程的总结:
- lwIP 内核不是线程安全的。如果在多线程环境中使用 lwIP,必须使用高层次的
Sequential
或socket
API。使用raw
API 时,需要自己保护好应用程序和协议栈核心代码。 - 在无操作系统环境中使用
raw
API:- 使用轮询接收数据,因为不会在中断中使用 lwIP 函数,不需要任何保护
- 使用中断接收数据,需要定义宏
SYS_LIGHTWEIGHT_PROT
来保护pbuf
和内存分配相关代码。
- 套接字通常不能被多个应用线程使用,因为
UDP
或TCP
控制块不能在多个线程之间共享。(目前在 udp 、netconn 上可以执行sendto
、recv
操作。)
可以从 rawapi.txt 文档中看一下关于多线程描述的演进过程。
2002 年 10 月 19:
lwIP 提供 2 种应用编程接口(API),用于与 TCP/IP 代码通讯:Sequential
API 和 RAW
API。
对于 Sequential
API,它提供了一种普通的、顺序的使用 lwIP 协议栈方法。它与 BSD 套接字 API非常相似。执行模型是基于 open - read - write - close
范式(注:顺序的由来)。由于 lwIP 协议栈本质上是基于事件的,因此 TCP/IP 内核代码和应用程序必须位于不同的线程中。
注:lwIP 版本大于等于 V0.5 才有 Sequential
API。
注:
初始版本。
这是 lwIP 的洪荒年代,版本大概是 lwip-0.6,没有找到具体的版本日期,只能从已知的版本日期推测这个时候,还没有关于多线程的描述。
2004 年 10 月 18:
lwIP 提供 2 种 应用编程接口(API),用于与 TCP/IP 代码通讯:
- 低层次的
core
、回调
或raw
API - 高层次的
Sequential
API
对于 Sequential
API,它提供了一种普通的、顺序的使用 lwIP 协议栈方法。它与 BSD 套接字 API非常相似。执行模型是基于阻塞 open - read - write - close
范式。由于 lwIP 协议栈本质上是基于事件的,因此 TCP/IP 内核代码和应用程序必须位于不同的线程中。
注:
本次更改的版本最早可以在 lwIP-1.1.0 中看到 。与初始版本相比,本质上没有改动,只是描述更加准确。
2009 年 5 月 7:
lwIP 提供 3 种 应用编程接口(API),用于与 TCP/IP 代码通讯:
- 低层次的
core
、回调
或raw
API - 高层次的
Sequential
API - BSD 风格的
socket
API
对于 Sequential
API,它提供了一种普通的、顺序的使用 lwIP 协议栈方法。它与 BSD 套接字 API非常相似。执行模型是基于阻塞 open - read - write - close
范式。由于 lwIP 协议栈本质上是基于事件的,因此 TCP/IP 内核代码和应用程序必须位于不同的线程中。
socket
API 是一种与现有应用程序(指使用 BSD 标准 socket
编写的代码)兼容的 API,目前它是建立在 Sequential
API之上的。socket
API 提供在其它平台(比如 unix / windows)运行 socket
API 所需的所有功能。但是,由于 Sequential
API 的限制,可能存在与标准 BSD socket
不兼容问题,需要对现有程序进行少量修改。
线程
lwIP 最初仅针对单线程环境。在增加多线程功能时,并没有使内核线程安全,而是采用了另一种方法:用一个主线程(称为 tcpip_thread
)运行 lwIP 内核。raw
API 只能在此线程中使用。使用 Sequential
或 socket
API 的应用程序线程通过 消息机制
与主线程通讯。
因此,可以从其它线程或 ISR(中断) 调用的函数列表非常有限!只有使用以下头文件中的 API 函数才是线程安全的:
- api.h
- netbuf.h
- netdb.h
- netifapi.h
- sockets.h
- sys.h
此外,在使用操作系统的情况下(NO_SYS=0),可以从多个线程(不是 ISR!)调用内存分配或释放函数,因为它们由 SYS_LIGHTWEIGHT_PROT
和信号量保护。
从 lwIP-1.3.0 开始,如果宏 SYS_LIGHTWEIGHT_PROT
和 LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
都设置为 1,则可以从另一个线程或 ISR 调用 pbuf_free()
。
注:
lwIP-1.3.0 发布于 2008 年 3 月 23,。
本次更改的版本最早可以在 lwIP-1.3.1 中看到。与 lwip-1.1.0 相比,最大的更新是
支持
BSD 风格的socket
API,以及对哪些文件是多线程安全的
进行了文档化描述。关于文档化
lwIP 线程安全要求
, 这是Kieran Mansley
提出的一个任务(见task #6683),起始于 2007 年 3 月 26,直到 2009 年 5 月 7 ,由Simon Goldschmid
在 rawapi.txt 中添加相关描述才结束。
2015 年 9 月 22
lwIP 提供 3 种 应用编程接口(API),用于与 TCP/IP 代码通讯:
- 低层次的
core
、回调
或raw
API - 高层次的
Sequential
API - BSD 风格的
socket
API
对于 raw
API(有时也称为 原生
API)是一种事件驱动的 API,在无操作系统的情况下,可以实现零拷贝发送和接收。
对于 Sequential
API,它提供了一种普通的、顺序的使用 lwIP 协议栈方法。它与 BSD 套接字 API非常相似。执行模型是基于阻塞 open - read - write - close
范式。由于 lwIP 协议栈本质上是基于事件的,因此 TCP/IP 内核代码和应用程序必须位于不同的线程中。
socket
API 是一种与现有应用程序(指使用 BSD 标准 socket
编写的代码)兼容的 API,目前它是建立在 Sequential
API之上的。socket
API 提供在其它平台(比如 unix / windows)运行 socket
API 所需的所有功能。但是,由于 Sequential
API 的限制,可能存在与标准 BSD socket
不兼容问题,需要对现有程序进行少量修改。
多线程
lwIP 最初仅针对单线程环境。在增加多线程功能时,并没有使内核线程安全,而是采用了另一种方法:用一个主线程(称为 tcpip_thread
)运行 lwIP 内核。如果在多线程环境下使用 lwIP 协议栈,raw
API 只能在 tcpip_thread
线程中使用,因为没有对 raw
API 函数做并发访问保护(除了 pbuf
和内存管理之外)。使用 Sequential
或 socket
API 的应用程序线程通过 消息机制
与主线程通讯。
因此,可以从其它线程或 ISR(中断) 调用的函数列表非常有限!只有使用以下头文件中的 API 函数才是线程安全的:
- api.h
- netbuf.h
- netdb.h
- netifapi.h
- pppapi.h
- sockets.h
- sys.h
此外,在使用操作系统的情况下(NO_SYS=0),可以从多个线程(不是 ISR!)调用内存分配或释放函数,因为它们由 SYS_LIGHTWEIGHT_PROT
和信号量保护。
Sequential
或 socket
API 函数针对核心线程(tcpip_thread
)是线程安全的,但是在控制块(control block)粒度上是不可重入的。也就是说,在没有适当锁定的情况下, UDP
或 TCP
控制块不能在多个线程之间共享。
如果宏 SYS_LIGHTWEIGHT_PROT
和 LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
都设置为 1,则可以从另一个线程或 ISR 调用 pbuf_free()
。
注:
本次更改的版本最早可以在 lwIP-2.0.0 中看到。
这是对 lwIP-1.3.1 相关文档的改进,描述更加准确。关于
多线程的注意事项
也已经完备。后续关于多线程的描述被移动到了doxygen docs
文档中,直到 lwIP-2.1.3 版本,也没有什么实质性更新。