电子说
一 rt-thread网络架构
如图所示,rt-thread的网络分为应用层、sal_socket、netdev、协议簇(at、lwip、wiznet)、网卡驱动五层。
应用层:调用BSD Socket API实现的网络应用,如前面介绍的paho-mqtt。
sal_socket:对socket的抽象,通过网卡(netdev)的pf(sal_proto_family)调用具体的协议簇。
netdev:netdev的私有数据保存协议簇pf(sal_proto_family),pf中的family用于匹配socket需要的协议簇。
协议簇:当socekt匹配上协议簇后,pf的skt_ops调用具体的协议簇。协议簇的实现在sal_socket文件夹下的impl文件夹下,在每一类协议簇的实现中,都有一个向netdev设置协议簇的接口,如lwip中的sal_lwip_netdev_set_pf_info。这样就可以通过netdev访问到具体的协议簇。
网卡驱动:底层硬件。
二 sal_socket
2.1 BSD socket
当我们在调用BSD socket写代码时,实际上是调用sal_xxx(如sal_socket),在sys/socket.h文件中,通过#define将socket转换成sal_socket的接口。
2.2 sal_init
sal_init从堆中分配出一个socket表sal_socket_table。sal_socket_table用于保存所有的sockets的信息,当需要创建一个sal_socket时,会从表中取出一个未使用的sal_socket,表的索引(数组下标)是sal_socket的描述符。
2.3 socket函数
2.3.1 socket_new
socket_new从sal_socket_table中获取一个未使用的socket,并返回描述符。
2.3.2 socket_init
socket_init根据domain在netdev_get_by_family函数中匹配netdev。socket原型为
int socket(int domain, int type, int protocol);
不同协议簇的domain值如下:
lwIP 协议栈: family = AF_INET、sec_family = AF_INET
AT Socket 协议栈: family = AF_AT、sec_family = AF_INET
WIZnet 硬件 TCP/IP 协议栈: family = AF_WIZ、sec_family = AF_INET
与之相应的,netdev私有数据所保存的协议簇sal_proto_family中有一个family字段,用于与socket进行匹配,这样socket函数通过doamin参数就可以指定使用lwip、at、wiznet三种协议簇的一种。
2.3.3 pf->skt_ops->socket
通过pf->skt_ops->socket调用具体协议簇的socket函数,如lwip的lwip_socket。
三 网卡的匹配和注册
3.1 网卡的匹配-netdev_get_by_family
for (node = &(netdev_list->list); node; node = rt_slist_next(node))
{
netdev = rt_slist_entry(node, struct netdev, list);
pf = (struct sal_proto_family *) netdev->sal_user_data;
if (pf && pf->skt_ops && pf->family == family && netdev_is_up(netdev))
{
rt_hw_interrupt_enable(level);
return netdev;
}
}
遍历netdev_list,查找与socket函数传入的domain(family)参数一致netdev。
3.2 网卡的注册-netdev_add
在component文件夹的driver文件夹下,不同网卡驱动最终会调用到netdev_add向netdev_list添加netdev,向内核注册一个网卡,以rw009为例。
rt_hw_wifi_init -> eth_device_init -> eth_device_init_with_flag -> eth_netif_device_init -> netdev_add。
全部0条评论
快来发表一下你的评论吧 !