• LwIP Application Developers Manual11---Initializing lwIP


    1.前言

    2.Initialization for simple lwIP

    查看doc/rawapi.txt来获得更多官方信息

    #if NO_SYS
     /* Network interface variables */
     struct ip_addr ipaddr, netmask, gw;
     struct netif netif;
     /* Set network address variables */
     IP4_ADDR(&gw, 192,168,0,1);
     IP4_ADDR(&ipaddr, 192,168,0,2);
     IP4_ADDR(&netmask, 255,255,255,0);
     /* The lwIP single-threaded core: initialize the network stack */ 
     lwip_init();
    #else /* lwIP in a multi-threaded system: initialize the network stack */ tcpip_init(tcpip_init_done, tcpip_init_done_param); /* implicitly calls lwip_init(); start new thread calls tcpip_init_done(tcpip_init_done_param); when tcpip init done tcpip_init_done and tcpip_init_done_param are user-defined (may be NULL). */ /* todo: wait for tcpip_init_done() ? */ #endif /* Bring up the network interface */ /* Hint: netif_init(); was already called by lwip_init(); above */ netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethhw_init, ethernet_input); /* ethhw_init() is user-defined */ /* use ip_input instead of ethernet_input for non-ethernet hardware */ /* (this function is assigned to netif.input and should be called by the hardware driver) */ netif_set_default(&netif); netif_set_up(&netif);

    更多关于tcpip_init的详细信息请查看Initialization using tcpip.c。关于网络接口的管理详情请看Network interfaces management

    在初始化完后,会发生什么呢?你可以继续阅读lwIP with or without an operating system。完整的例子可以在contrib/ports/unix/proj/路径中找到。

    3. Initialization using tcpip.c

    如果你打算使用tcpip线程,下面是lwIP初始化的例子:

    #include "lwip/tcpip.h"  
       
     struct netif my_netif;  
       
     err_t my_ip_init(struct ip_addr *ipaddr,  
                      struct ip_addr *netmask,  
                      struct ip_addr *gw,  
                      err_t (* init)(struct netif *netif),  
                      err_t (* input)(struct pbuf *p, struct netif *netif)) {  
         
        // Start the TCP/IP thread & init stuff  
        tcpip_init(NULL, NULL);  
        // WARNING: This must only be run after the OS has been started.  
        // Typically this is the case, however, if not, you must place this  
        // in a post-OS initialization  
        return netifapi_netif_add(&my_netif, ipaddr, netmask, gw, NULL, init, input);  
    }

    注:这个例子虽然假设使用静态IP,但是你可以将netif_set_up替换成dhcp_start或者autoip_start(详细请看Network interfaces management)

    4.Network interfaces management

    lwIP网络物理层的设备驱动被一个网络接口结构体所描述,与BSD很相似。网络接口保存在一个全局链表内,且被下一个指针所链接。

    4.1 Starting a network interface

    Step One: Add the interface

    为了创建一个新的网络接口,用户 为结构体 netif分配内存空间(但是初始化它的任何部分),并调用netif_add:

    struct *netif netif_add(struct netif *mynetif, struct ip_addr *ipaddr, struct ip_addr *netmask, 
                            struct ip_addr *gw, void *state, err_t (* init)(struct netif *netif), 
                            err_t (* input)(struct pbuf *p, struct netif *netif));

    用户指定一个IP地址,子网掩码和网关地址给该接口,这些值随后可以被改变

    (1)state

    State是一个特定于驱动的结构体,该结构体定义了许多其他”state”的必要信息来完成驱动的功能。

    一些驱动会要求先设置state变量,然后再调用netif_add,但是很多时候要求这个参数为NULL。检查你的驱动可以获得更多信息

    (2)init

    init要求一个设备驱动初始化的函数,该函数一旦被调用netif结构体已经被netif_add准备好了。如果该驱动已经被初始化在你其它地方的代码,这个参数可以设为NULL

    (3)input

    当它接收到新的数据包时,参数input将会被一个驱动调用。这个参数将会需要如下一些函数:

    ethernet_input

    如果你不是在一个单线程环境中使用lwIP协议栈并且该驱动使用ARP(比如,以太网设备),则该驱动将会调用该函数来处理ARP数据包包括IP数据包。

    ip_input

    如果你不是在一个单线程环境中使用lwIP协议栈并且该接口并不是一个以太网设备,则该驱动会直接调用IP协议。

    tcpip_ethinput

    如果你使用tcpip应用线程(查看lwIP多线程),则该驱动将使用ARP,并且要定义lwIP的选项ETHARP_TCPIP_ETHINPUT。该函数将被驱动使用来将所有的IP和ARP数据包发给input函数

     tcpip_input

    如果你使用tcpip应用线程并且已经定义了ETHART_TCPIP_INPUT选项。则该函数被驱动使用来将IP数据包发给input函数。(驱动会分开ARP数据包并将它直接发送给ARP模块)。(注意:在lwip1.4.1里并没有tcpip_ethinput(),tcp_input将会处理所有的ARP数据包)

    Step Two: Bring the interface up(打开接口)

    一个接口如果是up状态,那么你的应用程序就可以使用该接口进行输入和输出,如果是down状态,则相反。因此,在使用该接口前,你一定要打开该接口(状态为up)。打开接口动作的完成取决于该接口如何得到IP地址。打开/关闭(up/dwon)函数对每种获得IP地址方式的区别如下所示:

    n 静态IP地址:使用netif_set_up和netif_set_down。在你将接口打开前,你要确保已经设置了IP地址(通过netif_add或者netif_set_addr调用)。

    n DHCP:使用dhcp_start和dhcp_stop。dhcp_start函数将会打开该接口,当它获得一个地址时设置IP地址。

    n AUTOIP:使用autoip_start和autoip_stop。当它选中一个IP地址时,Autoip将会打开该接口并设置IP地址。

    为了测试一个netif是否打开,你可以使用netif_is_up

    4.2 Further netif management 

    如果你加入一个netif接口,则该接口将会被当成默认的接口,于是你可以调用netif_set_default来确定默认的接口。当IP协议栈试图选择合适的路径(路由)来发送数据包时,如果该协议栈不能决定使用哪个正确的接口,那么它将通过默认的接口发送数据。如果你使用一个静态IP地址,那么你可以通过函数netif_set_ipaddr,netif_set_gw,和netif_set_netmask来设置该网络接口的相关的参数。当然你也可以使用netif_set_addr来一次设置这3个地址参数。当在文件lwipopts.h中设置LWIP_NETIF_STATUS_CALLBACK时,则该协议栈将提供一个状态回调函数。当接口打开或关闭时,则该状态回调函数将会被调用。举例,当你想要记录IP地址(该IP地址通过DHCP来获得)并想知道该地址的变化情况时,你就可以使用状态函数的钩子函数。设置一个netif接口的状态回调函数如下所示:

    void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
  • 相关阅读:
    web前端学习(四)JavaScript学习笔记部分(8)-- JavaScript瀑布流
    localStorage对象简单应用
    html文档加载顺序简单理解
    回调函数理解(转载)
    web前端学习(四)JavaScript学习笔记部分(8)-- JavaScript 浏览器对象
    web前端学习(四)JavaScript学习笔记部分(7)-- JavaScript DOM对象控制HTML元素详解
    JS random函数深入理解(转载)
    web前端学习(四)JavaScript学习笔记部分(6)-- js内置对象
    下雪了-js下雪效果
    LESS笔记
  • 原文地址:https://www.cnblogs.com/smartjourneys/p/8214480.html
Copyright © 2020-2023  润新知