教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 精品文档 > 实用模板 >

LWIP之SOCKET的实现(7)

来源:网络收集 时间:2026-05-15
导读: return netif; } } } if ((netif_default == NULL) || (!netif_is_up(netif_default))) { snmp_inc_ipoutnoroutes(); return NULL; } /* no matching netif found, use default netif */ return netif_default; }

return netif; } } }

if ((netif_default == NULL) || (!netif_is_up(netif_default))) {

snmp_inc_ipoutnoroutes(); return NULL; }

/* no matching netif found, use default netif */ return netif_default; }

可以说这个函数的实现很简单,且作用也很容易看懂,就像其注释所说的一样。不过在这个函数中我们还是发现了一些什么,对了,就是struct netif *netif_list;【src\\core\\netif.c】的使用。既然这里都使用了这个网络接口链表,那它是在哪里被初始化的呢?

好了,首先我们发现在netif_add函数中有对netif_list的调用,netif_add是被do_netifapi_netif_add函数调用的,而do_netifapi_netif_add是在netifapi_netif_add中通过netifapi_msg被TCPIP_NETIFAPI调用的。问题似乎很清楚,只要找到nnetifapi_netif_add是被谁调用的就好了,然而,搜遍整个工程也没有发现这个函数的影子,除了一个声明一个实现外。My god,又进入死胡同了?好吧,这里先标识一下,待解【见下面的解释】

我们接着看ip_output_if这个函数,具体函数可参考【src\\core\\ipv4\\ip.c】。它的函数定义注释如下:

* Sends an IP packet on a network interface. This function constructs * the IP header and calculates the IP header checksum. If the source * IP address is NULL, the IP address of the outgoing network * interface is filled in as source address.

* If the destination IP address is IP_HDRINCL, p is assumed to already * include an IP header and p->payload points to it instead of the data.

再看最后一句:return netif->output(netif, p, dest);

嗯,看来这个netif还是关键啊,如果估计不错的话,接收的时候也要用到这个结构的。那就看它在什么地方被赋值的吧。又经过一番搜索,看来在目前的代码中是找不到的了。查看lwip协议栈的设计与实现,特别是网络接口层的那一节,终于明白了,原来这些是要有设备驱动来参与的:【一下为引用】

当收到一个信息包时,设备驱动程序调用input指针指向的函数。网络接口通过output指针连接到设备驱动。这个指针指向设备驱动中一个向物理网络发送信息包

的函数,当信息包包被发送时由IP层调用,这个字段由设备驱动的初始设置函数填充。

接下来就是ip层的接收过程了。刚才上面也有提到驱动设备收到包,丢给netif的input函数,这个input函数也是设备驱动层来设置的。无非有两个可能,一个是ip_input,另外一个就是tcpip_input。因为tcpip_input函数的处理是最终调用到了ip_input【在tcpip_thread中】。按照正常情况下应该是ip_input函数的,我们先来看下这个函数。

* This function is called by the network interface device driver when * an IP packet is received. The function does the basic checks of the * IP header such as packet size being at least larger than the header * size etc. If the packet was not destined for us, the packet is * forwarded (using ip_forward). The IP checksum is always checked.

嗯,那就这样吧,到这里我们可以说IP层的发送流程已经走完了。

原型:err_t ip_input(struct pbuf *p, struct netif *inp)

该函数大致的处理过程是:处理ip包头;找到对应的netif;检查如果是广播或多播包,则丢掉;如果是tcp协议的话就直接调用了tcp_input函数处理数据。

到此,ip层的东西大致就说完了。最后,由于tcp和ip层的东西都说完了,所以此时我们顺便看下,tcpip的整体实现,这个主要是在src\\api\\tcpip.c文件中实现。我们知道发送过程是由socket直接调用的,所以这个文件中不涉及,说白了,这个文件主要是涉及到整个接收过程。这里实现的函数有tcpip_input,和tcpip_thread以及tcpip_init函数。

Tcpip_init函数很简单就是创建系统线程(sys_thread_new)tcpip_thread。 Tcpip_thread函数的注释如下:

* The main lwIP thread. This thread has exclusive access to lwIP core functions

* (unless access to them is not locked). Other threads communicate with this

* thread using message boxes.

它的整个过程就是一直从mbox中取出msg,对各种msg的一个处理过程。 Tcpip_input函数,是在tcpip_thread中被调用的处理设备驱动接收到的信息包,并调用

ip_input来进一步处理。

整个启动过程: main---> vlwIPInit() void vlwIPInit( void ) {

/* Initialize lwIP and its interface layer. */ sys_init();

mem_init(); memp_init(); pbuf_init(); netif_init(); ip_init();

sys_set_state(( signed portCHAR * ) \ tcpip_init( NULL, NULL ); sys_set_default_state(); }

从上面我们知道,tcpip_init创建tcpip_thread 在tcpip_thread的开始有如下代码: (void)arg; ip_init();

#if LWIP_UDP udp_init(); #endif

#if LWIP_TCP tcp_init(); #endif

#if IP_REASSEMBLY

sys_timeout(1000, ip_timer, NULL); #endif

if (tcpip_init_done != NULL) {

tcpip_init_done(tcpip_init_done_arg); }

下面是tcp_init的实现 Void tcp_init(void) {

/* Clear globals. */

tcp_listen_pcbs.listen_pcbs = NULL; tcp_active_pcbs = NULL; tcp_tw_pcbs = NULL; tcp_tmp_pcb = NULL; /* initialize timer */ tcp_ticks = 0; tcp_timer = 0; }

LWIP的底层结构(物理层)

我们前面讲到说是ip层的发送和接收都是直接调用了底层,也就是设备驱动层的函数实现,在这里暂且称之为物理层吧。下面就接着ip层的讲,不过由于这里的设备驱动各平台的都不一样,为此,我们选择ARM9_STR91X_IAR这个Demo作为实例,该平台的网络设备驱动在\\library\\source\\91x_enet.c文件中。而ethernetif.c文件就是我们需要的,它是连接设备驱动程序与ip层的桥梁。

Ethernetif.c文件中提供的函数主要有以下这么几个: (1) low_level_init (2) low_level_input (3) low_level_output (4) ethernetif_init (5) ethernetif_input (6) ethernetif_output

这里对外的接口只有ethernetif_init函数,它是main函数中通过

netif_add( &EMAC_if, &xIpAddr, &xNetMast, &xGateway, NULL, ethernetif_init, tcpip_input );来被调用的。我们可以清楚的看到,tcpip_input的使用,它就是被用来当有数据接收的时候被调用的以使接收到的数据进入tcpip协议栈。

在netif_add函数中,我们可以看到 netif->input = input;

if (init(netif) != ERR_OK) {

return NULL; }

Ok,从这里就进入到ethernetif_init函数了,在这个函数中,我们主要看以下几句:

netif->output = ethernetif_output; netif->linkoutput = low_level_output; low_level_init(netif); etharp …… 此处隐藏:3523字,全部文档内容请下载后查看。喜欢就下载吧 ……

LWIP之SOCKET的实现(7).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wendang/520675.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)