【正文】
分析看,上述的接口在應(yīng)用 lwip 的協(xié)議棧時(shí),需要重點(diǎn)關(guān)注。該接口中,實(shí)現(xiàn)dhcp 報(bào)文的 協(xié)議處理。最后啟動(dòng) dhcp 申請(qǐng)。 dhcp 模塊用于獲取設(shè)備 ip 地址的相關(guān)信息。其主要入口函數(shù)為: err_t ip_input(struct pbuf *p, struct if *inp) 該接口通過(guò)判斷輸入報(bào)文的協(xié)議類型,將其輸入到相應(yīng)的上層協(xié)議模塊中去。 在 etharp_output 接口中,判斷報(bào)文類型,如果是廣播包或者組播包,就調(diào)用 etharp_send_ip(組裝目標(biāo) mac和源 mac)接口, etharp_send_ip調(diào)用 if結(jié)構(gòu)中的設(shè)備驅(qū)動(dòng)注冊(cè)的 linkoutput鉤子函數(shù)發(fā)送最終報(bào)文。 如果是 ip 報(bào)文,該接口就調(diào)用 etharp_ip_input 進(jìn)行 arp更新,并調(diào)用 ip_input 接口,將報(bào)文提交給 ip 層。 這是對(duì) pbuf 結(jié)構(gòu)體進(jìn)行操作的函數(shù)。 err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)。 第 15 頁(yè) 共 18 頁(yè) u8_t pbuf_clen(struct pbuf *p)。 u8_t pbuf_header(struct pbuf *p, s16_t header_size)。當(dāng)接收網(wǎng)絡(luò)數(shù)據(jù)包時(shí),我們選擇的 pbuf 是 PBUF_POOL類型的。 typedef enum { PBUF_RAM, /* pbuf data is stored in RAM */ PBUF_ROM, /* pbuf data is stored in ROM */ PBUF_REF, /* pbuf es from the pbuf pool */ PBUF_POOL /* pbuf payload refers to RAM */ } pbuf_type。所以放在了一起。所以 input 和 output 函數(shù)指針是直接指向網(wǎng)絡(luò)驅(qū)動(dòng)收發(fā)接口函數(shù)的。這個(gè)字段由設(shè)備驅(qū)動(dòng)的初始設(shè)置 函數(shù) 填充。 這個(gè)結(jié)構(gòu)體里所有的成員的作用都已經(jīng)注釋了,這里我們只關(guān)心兩個(gè)成員: err_t (* input)(struct pbuf *p, struct if *inp)。 endif /* LWIP_NETIF_HWADDRHINT */ if ENABLE_LOOPBACK /* List of packets to be queued for ourselves. */ struct pbuf *loop_first。 u32_t ifoutnucastpkts。 u32_t ifinnucastpkts。 /** (estimate) link speed */ u32_t link_speed。 /** flags (see NETIF_FLAG_ above) */ u8_t flags。 endif if LWIP_NETIF_HOSTNAME /* the hostname for this if, NULL is a valid value */ char* hostname。 endif /* LWIP_NETIF_STATUS_CALLBACK */ if LWIP_NETIF_LINK_CALLBACK /** This function is called when the if link is set to up or down */ void (* link_callback)(struct if *if)。 /** This function is called by the work device driver 第 12 頁(yè) 共 18 頁(yè) * to pass a packet up the TCP/IP stack. */ err_t (* input)(struct pbuf *p, struct if *inp)。 struct if { /** pointer to next in linked list */ struct if *next。 Netif 模塊為協(xié)議棧與底層驅(qū)動(dòng)的接口模塊,其將底層的一個(gè)網(wǎng)口設(shè)備描述成協(xié)議棧的一個(gè)接口設(shè)備( interface)。 首先調(diào)用 lwip_init()初始化了所有的子模塊。 mbox = sys_mbox_new(TCPIP_MBOX_SIZE)。 第 11 頁(yè) 共 18 頁(yè) 【 2】 初始化模塊 初始化模塊(這里主要講的是 TCP 協(xié)議的初始化模塊)主要在文件 api/ 中 。比如,通過(guò)宏,配置了 mem管理模塊的參數(shù)。 由于篇幅限制,不能對(duì)每個(gè) 源文件都做介紹。 FreeRTOS 這個(gè)文件夾不需要關(guān)心,因?yàn)檫@是基于實(shí)時(shí)操作系統(tǒng)的,而我們現(xiàn)在做的項(xiàng)目是基于單任務(wù)的,無(wú)需操作系統(tǒng)的支持。 Ipv6文件夾我們不必關(guān)心。所以直接忽略。這個(gè)文件提供了與底層網(wǎng)絡(luò)驅(qū)動(dòng)的一個(gè)接口。當(dāng)然還有一些 PPPOE等協(xié)議。 目錄里還提供了 RAW API接口的實(shí)現(xiàn)。 core 目錄: ICMP, IP, TCP, UDP協(xié)議的實(shí)現(xiàn)文件,以及一些輔助函數(shù), LWIP實(shí)現(xiàn)的核心代碼。 網(wǎng)絡(luò)接口層是和底層硬件驅(qū)動(dòng)交互的層。事實(shí)上, LWIP 協(xié)議棧使用的是內(nèi)存共享技術(shù),各層都能訪問(wèn)這段共享內(nèi)存,各層傳遞的就是數(shù)據(jù)結(jié)構(gòu)指針,所以 LWIP 協(xié)議棧降低了內(nèi)存復(fù)制所產(chǎn)生的性能損失) 。這里不列出。其中RAW API 主要是采用回調(diào)函數(shù)的方式來(lái)完成數(shù)據(jù)的發(fā)送和接收, RAW API 接口寫的應(yīng)用程序與 LWIP 協(xié)議棧處在同一個(gè)進(jìn)程(或者稱任務(wù))中。 LWIP邏輯上被分為四個(gè)層:應(yīng)用層,傳輸層,網(wǎng)絡(luò)層和網(wǎng)絡(luò)接口層。其中這里最主要的是 TCP 協(xié)議模塊的實(shí)現(xiàn)。每個(gè)協(xié) 議都以模塊的形式被實(shí)現(xiàn)。 LWIP各層之間沒(méi)有明顯的界限,各層之間都可以訪問(wèn)到共享在內(nèi)存中的數(shù)據(jù)。 傳統(tǒng)的,或者說(shuō)是典型的 TCP/IP協(xié)議族的設(shè)計(jì)都是按照分層的思想來(lái)設(shè)計(jì)的。如果對(duì) LWIP 協(xié)議棧本身沒(méi)什么興趣的,可以跳過(guò)第一、二、三章,直接閱讀第四章,使用我們的接口代替第四章的接口就行了。然后用我們自己的驅(qū)動(dòng)網(wǎng)卡的接口函數(shù)替代程序中的接口。 LWIP是 瑞典 計(jì)算機(jī)科學(xué)院開(kāi)發(fā)的一套用于嵌入式系統(tǒng)的開(kāi)放源代碼 的輕量級(jí)