日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LwIP 之一 源码目录文件详解及移植说明

發(fā)布時(shí)間:2024/10/14 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LwIP 之一 源码目录文件详解及移植说明 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?? lwIP 是 TCP/IP 協(xié)議套件的一個(gè)小型獨(dú)立實(shí)現(xiàn)。lwIP TCP/IP 實(shí)現(xiàn)的重點(diǎn)是減少 RAM 使用同時(shí)仍然有一個(gè)完整的 TCP。 這使得 lwIP 適合使用在具有數(shù) 10 千字節(jié)的可用 RAM 和空間大約 40 千字節(jié)的代碼 ROM 的嵌入式系統(tǒng)中。
?? lwIP 最開始由 Adam Dunkels 在瑞典計(jì)算機(jī)科學(xué)研究所(SICS)的計(jì)算機(jī)與網(wǎng)絡(luò)體系結(jié)構(gòu)(CNA)實(shí)驗(yàn)室時(shí)開發(fā),現(xiàn)在由全球開發(fā)人員網(wǎng)絡(luò)開發(fā)和維護(hù)。

版本變更

2.1.x

?? LWIP 從 2.0.3 版本,直接跳到了 2.1.0 版本,又是一個(gè)大的版本更新。增加了一些功能!同時(shí)源碼的目錄結(jié)構(gòu)也有了一定的變化(增加了一些文件)! 按照 LWIP 的發(fā)布策略,以后 2.1.x 都是從 2.1.0 版本開始的 BUG 修復(fù)版本,最新的 BUG 修復(fù)版本是 2.1.2。具體變化參見源碼目錄下的 CHANGELOG 文件。下圖顯示了 2.0.3 版 和 2.1.2 版的文件對比差異:

??關(guān)于這個(gè)版本,官網(wǎng)有個(gè)這么一句話 “ Oh, and this will be the last release with a separate contrib repository. I’ll be merging the files from contrib into the main repository soon after the release. In the git world, having two separate repositories just doesn’t work nice. ” 。大意就是,這是帶有獨(dú)立 contrib 庫的最后一版本,后續(xù)會將 contrib 合并到 LWIP 主版本庫中。
??其次,如果詳細(xì)去看 LWIP 的說明文檔,會發(fā)現(xiàn)文檔中有些描述還是之前的,并沒有跟隨版本變更而改變!例如在doc目錄下,原來的系統(tǒng)結(jié)構(gòu)模板文件名為sys_arch.txt,在此版本沒有了這個(gè)文件,但是說明文檔中,仍然有這部分的介紹!

2.0.x

?? LWIP 從 1.4.1 版本,直接跳到了 2.0.x 版本,是一個(gè)大的版本更新。源碼結(jié)構(gòu)變化比較大! 按照 LWIP 的發(fā)布策略,以后 2.0.x 都是從 2.0.0 版本開始的 BUG 修復(fù)版本,最終的 BUG 修復(fù)版本是 2.0.3。2.0.3 版本修復(fù)自 2.0.2 以來的一些錯(cuò)誤,沒有任何功能的變化。具體如下:

  • 2017-09-11: Simon Goldschmidt
    • tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data)
  • 2017-08-02: Abroz Bizjak/Simon Goldschmidt
    • multiple fixes in IPv4 reassembly (leading to corrupted datagrams received)
  • 2017-03-30: Simon Goldschmidt
    • dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf
  • 2017-03-23: Dirk Ziegelmeier
    • dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work)

1.x.x

最終版本為 1.4.1。

源碼目錄文件

??要使用 LWIP 的源碼由兩部分組成,分別為 LWIP 和 contrib 。這兩個(gè)是由兩個(gè)獨(dú)立的版本庫,并且由不同的人來負(fù)責(zé)的!我們在實(shí)際使用 LWIP 時(shí),這兩部分都是需要使用的!

其中,contrib 中是一些和平臺移植相關(guān)的代碼,LWIP 則是 TCP/IP 協(xié)議棧的核心源碼!
??下面我就以 2.0.3 版為例!從 1.4.1 到 2.0.3(從 2.0.0 開始),LwIP 的源碼有了一定的變化,甚至于源碼的文件結(jié)構(gòu)也不一樣,內(nèi)部的一些實(shí)現(xiàn)源文件也被更新和替換了。其源碼目錄結(jié)構(gòu)如下所示(對于簡單的文件以注釋的形式給出,核心源碼下文會詳細(xì)說明):

LWIP-2.0.3 │ CHANGELOG // 版本更新記錄,從中可以看到 LwIP 不同版本的變化 │ COPYING // 版權(quán)說明 │ FILES // 其中說明了其所在目錄下的各目錄或文件的用途。在不同的目錄下會有不同的該文件 │ README // 簡介文檔 │ UPGRADING // 版本升級后可能出現(xiàn)不兼容,該文檔記錄了從老版本升級需要修改的地方。對于升級自己使用的 LwIP 版本時(shí)很有用處。 ├─doc │ │ contrib.txt // LwIP 作為開源軟件,如果想要為其做貢獻(xiàn),則需要遵循一定的準(zhǔn)則,例如:提交代碼的風(fēng)格、報(bào)告Bug等。該文檔給出了詳細(xì)的貢獻(xiàn)準(zhǔn)則。 │ │ doxygen_docs.zip // 用 doxygen 生成的 LwIP 的配套文檔 │ │ FILES // 其中說明了該目錄下的每個(gè)文件的用途 │ │ mdns.txt // MDNS 的說明文檔 │ │ mqtt_client.txt │ │ NO_SYS_SampleCode.c │ │ ppp.txt // lwIP的PPP接口文檔 │ │ rawapi.txt // 告訴讀者怎樣使用協(xié)議棧的 Raw/Callback API 進(jìn)行編程 │ │ savannah.txt // 說明了如何獲取當(dāng)前的開發(fā)源代碼 │ │ sys_arch.txt // 在有操作系統(tǒng)的移植的時(shí)候會被使用到,包含了移植說明,規(guī)定了移植者需要實(shí)現(xiàn)的函數(shù)、宏定義等,后面有詳細(xì)說明。 │ └─doxygen // doxygen 腳本,主要用來維護(hù) LwIP 的配套文檔。對于使用LwIP來說用不到 │ │ generate.bat │ │ generate.sh │ │ lwip.Doxyfile │ │ main_page.h │ └─output │ index.html ├─src /* 源碼文件部分下面獨(dú)立詳細(xì)說明 */ │ │ Filelists.mk │ │ FILES // 主要記錄了該目錄下每個(gè)文件、目錄的用途 │ ├─api │ │ api_lib.c │ │ api_msg.c │ │ err.c │ │ netbuf.c │ │ netdb.c │ │ netifapi.c │ │ sockets.c │ │ tcpip.c │ ├─apps │ │ ├─httpd │ │ │ │ fs.c │ │ │ │ fsdata.c │ │ │ │ fsdata.h │ │ │ │ httpd.c │ │ │ │ httpd_structs.h │ │ │ ├─fs │ │ │ │ │ 404.html │ │ │ │ │ index.html │ │ │ │ └─img │ │ │ │ sics.gif │ │ │ └─makefsdata │ │ │ makefsdata │ │ │ makefsdata.c │ │ │ readme.txt │ │ ├─lwiperf │ │ │ lwiperf.c │ │ ├─mdns │ │ │ mdns.c │ │ ├─mqtt │ │ │ mqtt.c │ │ ├─netbiosns │ │ │ netbiosns.c │ │ ├─snmp │ │ │ snmpv3.c │ │ │ snmpv3_dummy.c │ │ │ snmpv3_mbedtls.c │ │ │ snmpv3_priv.h │ │ │ snmp_asn1.c │ │ │ snmp_asn1.h │ │ │ snmp_core.c │ │ │ snmp_core_priv.h │ │ │ snmp_mib2.c │ │ │ snmp_mib2_icmp.c │ │ │ snmp_mib2_interfaces.c │ │ │ snmp_mib2_ip.c │ │ │ snmp_mib2_snmp.c │ │ │ snmp_mib2_system.c │ │ │ snmp_mib2_tcp.c │ │ │ snmp_mib2_udp.c │ │ │ snmp_msg.c │ │ │ snmp_msg.h │ │ │ snmp_netconn.c │ │ │ snmp_pbuf_stream.c │ │ │ snmp_pbuf_stream.h │ │ │ snmp_raw.c │ │ │ snmp_scalar.c │ │ │ snmp_table.c │ │ │ snmp_threadsync.c │ │ │ snmp_traps.c │ │ ├─sntp │ │ │ sntp.c │ │ └─tftp │ │ tftp_server.c │ ├─core │ │ │ def.c │ │ │ dns.c │ │ │ inet_chksum.c │ │ │ init.c │ │ │ ip.c │ │ │ mem.c │ │ │ memp.c │ │ │ netif.c │ │ │ pbuf.c │ │ │ raw.c │ │ │ stats.c │ │ │ sys.c │ │ │ tcp.c │ │ │ tcp_in.c │ │ │ tcp_out.c │ │ │ timeouts.c │ │ │ udp.c │ │ ├─ipv4 │ │ │ autoip.c │ │ │ dhcp.c │ │ │ etharp.c │ │ │ icmp.c │ │ │ igmp.c │ │ │ ip4.c │ │ │ ip4_addr.c │ │ │ ip4_frag.c │ │ └─ipv6 │ │ dhcp6.c │ │ ethip6.c │ │ icmp6.c │ │ inet6.c │ │ ip6.c │ │ ip6_addr.c │ │ ip6_frag.c │ │ mld6.c │ │ nd6.c │ ├─include │ │ ├─lwip │ │ │ │ api.h │ │ │ │ arch.h │ │ │ │ autoip.h │ │ │ │ debug.h │ │ │ │ def.h │ │ │ │ dhcp.h │ │ │ │ dhcp6.h │ │ │ │ dns.h │ │ │ │ err.h │ │ │ │ errno.h │ │ │ │ etharp.h │ │ │ │ ethip6.h │ │ │ │ icmp.h │ │ │ │ icmp6.h │ │ │ │ igmp.h │ │ │ │ inet.h │ │ │ │ inet_chksum.h │ │ │ │ init.h │ │ │ │ ip.h │ │ │ │ ip4.h │ │ │ │ ip4_addr.h │ │ │ │ ip4_frag.h │ │ │ │ ip6.h │ │ │ │ ip6_addr.h │ │ │ │ ip6_frag.h │ │ │ │ ip_addr.h │ │ │ │ mem.h │ │ │ │ memp.h │ │ │ │ mld6.h │ │ │ │ nd6.h │ │ │ │ netbuf.h │ │ │ │ netdb.h │ │ │ │ netif.h │ │ │ │ netifapi.h │ │ │ │ opt.h │ │ │ │ pbuf.h │ │ │ │ raw.h │ │ │ │ sio.h │ │ │ │ snmp.h │ │ │ │ sockets.h │ │ │ │ stats.h │ │ │ │ sys.h │ │ │ │ tcp.h │ │ │ │ tcpip.h │ │ │ │ timeouts.h │ │ │ │ udp.h │ │ │ ├─apps │ │ │ │ FILES │ │ │ │ fs.h │ │ │ │ httpd.h │ │ │ │ httpd_opts.h │ │ │ │ lwiperf.h │ │ │ │ mdns.h │ │ │ │ mdns_opts.h │ │ │ │ mdns_priv.h │ │ │ │ mqtt.h │ │ │ │ mqtt_opts.h │ │ │ │ netbiosns.h │ │ │ │ netbiosns_opts.h │ │ │ │ snmp.h │ │ │ │ snmpv3.h │ │ │ │ snmp_core.h │ │ │ │ snmp_mib2.h │ │ │ │ snmp_opts.h │ │ │ │ snmp_scalar.h │ │ │ │ snmp_table.h │ │ │ │ snmp_threadsync.h │ │ │ │ sntp.h │ │ │ │ sntp_opts.h │ │ │ │ tftp_opts.h │ │ │ │ tftp_server.h │ │ │ ├─priv │ │ │ │ api_msg.h │ │ │ │ memp_priv.h │ │ │ │ memp_std.h │ │ │ │ nd6_priv.h │ │ │ │ tcpip_priv.h │ │ │ │ tcp_priv.h │ │ │ └─prot │ │ │ autoip.h │ │ │ dhcp.h │ │ │ dns.h │ │ │ etharp.h │ │ │ ethernet.h │ │ │ icmp.h │ │ │ icmp6.h │ │ │ igmp.h │ │ │ ip.h │ │ │ ip4.h │ │ │ ip6.h │ │ │ mld6.h │ │ │ nd6.h │ │ │ tcp.h │ │ │ udp.h │ │ ├─netif │ │ │ │ etharp.h │ │ │ │ ethernet.h │ │ │ │ lowpan6.h │ │ │ │ lowpan6_opts.h │ │ │ │ slipif.h │ │ │ └─ppp │ │ │ │ ccp.h │ │ │ │ chap-md5.h │ │ │ │ chap-new.h │ │ │ │ chap_ms.h │ │ │ │ eap.h │ │ │ │ ecp.h │ │ │ │ eui64.h │ │ │ │ fsm.h │ │ │ │ ipcp.h │ │ │ │ ipv6cp.h │ │ │ │ lcp.h │ │ │ │ magic.h │ │ │ │ mppe.h │ │ │ │ ppp.h │ │ │ │ pppapi.h │ │ │ │ pppcrypt.h │ │ │ │ pppdebug.h │ │ │ │ pppoe.h │ │ │ │ pppol2tp.h │ │ │ │ pppos.h │ │ │ │ ppp_impl.h │ │ │ │ ppp_opts.h │ │ │ │ upap.h │ │ │ │ vj.h │ │ │ └─polarssl │ │ │ arc4.h │ │ │ des.h │ │ │ md4.h │ │ │ md5.h │ │ │ sha1.h │ │ └─posix │ │ │ errno.h │ │ │ netdb.h │ │ └─sys │ │ socket.h │ └─netif │ │ ethernet.c │ │ ethernetif.c │ │ FILES │ │ lowpan6.c │ │ slipif.c │ └─ppp │ │ auth.c │ │ ccp.c │ │ chap-md5.c │ │ chap-new.c │ │ chap_ms.c │ │ demand.c │ │ eap.c │ │ ecp.c │ │ eui64.c │ │ fsm.c │ │ ipcp.c │ │ ipv6cp.c │ │ lcp.c │ │ magic.c │ │ mppe.c │ │ multilink.c │ │ ppp.c │ │ pppapi.c │ │ pppcrypt.c │ │ PPPD_FOLLOWUP │ │ pppoe.c │ │ pppol2tp.c │ │ pppos.c │ │ upap.c │ │ utils.c │ │ vj.c │ └─polarssl │ arc4.c │ des.c │ md4.c │ md5.c │ README │ sha1.c └─test // 一些協(xié)議棧內(nèi)核測試程序.在實(shí)際使用時(shí)一般用不到!可直接刪除。├─fuzz│ │ config.h│ │ fuzz.c│ │ lwipopts.h│ │ Makefile│ │ output_to_pcap.sh│ │ README│ └─inputs│ ├─arp│ │ arp_req.bin│ ├─icmp│ │ icmp_ping.bin│ ├─ipv6│ │ neighbor_solicitation.bin│ │ router_adv.bin│ ├─tcp│ │ tcp_syn.bin│ └─udp│ udp_port_5000.bin└─unit│ lwipopts.h│ lwip_check.h│ lwip_unittests.c├─core│ test_mem.c│ test_mem.h│ test_pbuf.c│ test_pbuf.h├─dhcp│ test_dhcp.c│ test_dhcp.h├─etharp│ test_etharp.c│ test_etharp.h├─ip4│ test_ip4.c│ test_ip4.h├─mdns│ test_mdns.c│ test_mdns.h├─tcp│ tcp_helper.c│ tcp_helper.h│ test_tcp.c│ test_tcp.h│ test_tcp_oos.c│ test_tcp_oos.h└─udptest_udp.ctest_udp.h

??在LwIP的源碼包中,一共包含三個(gè)目錄:doc、src、test。分別對應(yīng):源碼的文檔、源碼、測試代碼。最新版的源碼與早期源碼在某些目錄文件是有區(qū)別的。以下主要說明 src ,即:源碼部分。

api目錄

??LwIP 提供了兩種類型的 API : Callback-style APIsSequential-style APIs 。其中,Callback-style APIs 即為LwIP最底層的接口,被稱為Raw API或者Native API;而Sequential-style APIs主要是對底層接口進(jìn)行了封裝,主要包含:Netconn API、NETIF API和Socket API。在實(shí)際使用中,使用者可以任選一種API來使用。
??api目錄下主要包含對底層API(raw API)封裝后的高級API的代碼。 如果直接使用底層的的Raw API,則不需要該目錄下的文件。而封裝后的高級別的這兩種API實(shí)現(xiàn)的原理都是通過引進(jìn)郵箱和信號量等通信與同步機(jī)制,來實(shí)現(xiàn)對內(nèi)核中***Raw API(native API)***函數(shù)的封裝和調(diào)用。要使用這兩種類型的API,需要底層操作系統(tǒng)的支持。

  • Raw API:(有時(shí)稱為native API)是一個(gè)設(shè)計(jì)用于在沒有操作系統(tǒng)時(shí),實(shí)現(xiàn)零拷貝發(fā)送和接收的事件驅(qū)動的API。 這個(gè)API也被核心堆棧用于各種協(xié)議之間的交互。 這是在沒有操作系統(tǒng)的情況下,運(yùn)行l(wèi)wIP時(shí)唯一可用的API
    ??因?yàn)镃allback/Raw API是協(xié)議棧提供的三種編程接口中最復(fù)雜的一種, 它通過直接與協(xié)議棧內(nèi) 核函數(shù)交互以實(shí)現(xiàn)編程,所以整個(gè)過程比較復(fù)雜。源碼的doc目錄下有一個(gè)專門的文檔:rawapi.txt說明了具體如何使用Raw API。
  • Netconn API: 為普通的、順序的程序提供了使用lwIP棧的方法。 線程安全,僅從非TCPIP線程調(diào)用。 基于網(wǎng)絡(luò)緩沖區(qū)(包含數(shù)據(jù)包緩沖區(qū)(PBUF))的TX / RX處理,以避免復(fù)制數(shù)據(jù)。這與BSD Socket API非常相似。 執(zhí)行模型基于 打開-讀取-寫入-關(guān)閉 范例。 由于TCP / IP堆棧本質(zhì)上是事件,所以TCP / IP代碼和應(yīng)用程序必須駐留在不同的執(zhí)行上下文(線程)中。
  • Socket API: 它是建立在Netconn API之上的。其主要是由于BSD Socket API是網(wǎng)絡(luò)通信的一個(gè)實(shí)現(xiàn)。線程安全,僅從非TCPIP線程調(diào)用。BSD Socket API已經(jīng)是網(wǎng)絡(luò)套接字的事實(shí)上的抽象標(biāo)準(zhǔn)。目前,所有主流操作系統(tǒng)均實(shí)現(xiàn)了BSD Socket API。出于此,LwIP也提供了一套BSD Socket API。但是,標(biāo)準(zhǔn) socket 庫中的部分函數(shù)仍無法直接通過封裝 Netconn API 來實(shí)現(xiàn),因此 LwIP 中提供的socket 函數(shù)并不完整,用戶最好不要使用它進(jìn)行實(shí)際應(yīng)用程序開發(fā)。對應(yīng)文件為posix/sys/socket.h。

以下為每個(gè)文件的具體說明:

  • api_lib.c: 包含 對外提供的 sequential API 函數(shù)的實(shí)現(xiàn)。函數(shù)名均以netconn_開頭。主要分為三組API:同時(shí)可用于TCP和UDP的API、只能用于TCP的API、只能用于UDP的API。
  • api_msg.c: 包含sequential API內(nèi)部自己調(diào)用的函數(shù)的實(shí)現(xiàn)。主要包含API消息的封裝和處理函數(shù)
  • err.c: 錯(cuò)誤管理模塊
  • netbuf.c: 包含了上層數(shù)據(jù)包管理函數(shù)的實(shí)現(xiàn)。應(yīng)用程序描述待發(fā)送數(shù)據(jù)和已接收數(shù)據(jù)的基本結(jié)構(gòu)。該結(jié)構(gòu)只是對內(nèi)核 pbuf 的簡單封裝,避免了數(shù)據(jù)的拷貝。緩沖區(qū)不能在多個(gè)線程之間共享。
  • netdb.c: 包含與主機(jī)名字轉(zhuǎn)換相關(guān)的函數(shù),主要在 socket 中被使用到
  • netifapi.c: 包含了上層網(wǎng)絡(luò)接口管理函數(shù)的實(shí)現(xiàn)
  • sockets.c: 包含了 Socket API 函數(shù)的實(shí)現(xiàn)
  • tcpip.c: 包含了上層 API 與協(xié)議棧內(nèi)核交互的函數(shù),它是整個(gè)上層 API 功能得以實(shí)現(xiàn)的一個(gè)樞紐,其實(shí)現(xiàn)的功能可以簡單理解為:從 API 函數(shù)處接收消息,然后將消息遞交給內(nèi)核函數(shù),內(nèi)核函數(shù)根據(jù)消息做出相應(yīng)的處理。

apps目錄

??使用lwIP低級raw API編寫的高層應(yīng)用程序。

core目錄

??TCP/IP 協(xié)議棧的核心部分。主要包含協(xié)議實(shí)現(xiàn)、內(nèi)存和緩沖區(qū)管理以及底層raw API的實(shí)現(xiàn)。它包含了IP、ICMP、IGMP、TCP、UDP 等核 心協(xié)議以及建立在它們基礎(chǔ)上的 DNS、DHCP、SNMP 等上層應(yīng)用協(xié)議。內(nèi)核源代碼可以單獨(dú)運(yùn)行,且不需要操作系統(tǒng)的支持。即:直接使用 raw API 編程。

  • ipv4目錄: 包含了IPv4 標(biāo)準(zhǔn)中與IP層數(shù)據(jù)包處理相關(guān)的所有代碼

  • autoip.c: 這是lwIP TCP / IP協(xié)議棧的AutoIP實(shí)現(xiàn)。 它旨在符合RFC 3927。

  • dhcp.c: 實(shí)現(xiàn)了DHCP 客戶端的所有代碼,DHCP 稱為動態(tài)主機(jī)配置協(xié)議,DHCP 可以使計(jì)算機(jī)使用者不必為主機(jī)的IP 地址的分配問題而煩惱。DHCP 也是一個(gè)上層應(yīng) 用程序, 通常DHCP客戶端通過使用UDP提供的功能來實(shí)現(xiàn)與DHCP服務(wù)器的通信, 從DHCP 服務(wù)器處獲得一個(gè)有效的IP 地址

  • etharp.c: 包含了ARP 協(xié)議實(shí)現(xiàn)的相關(guān)函數(shù),ARP 協(xié)議是以太網(wǎng)通信中的重要部分, 主要用來實(shí)現(xiàn)主機(jī)以太網(wǎng)物理地址到IP 地址的映射。這點(diǎn)是非常必要的,以太網(wǎng)中底層數(shù)據(jù)包的發(fā)送是基于網(wǎng)卡物理地址的,而不是主機(jī)的IP地址。 通過ARP協(xié)議, 主機(jī)可以發(fā)送請求, 得到鄰居節(jié)點(diǎn)的IP 地址與物理地址等信息,為以太網(wǎng)數(shù)據(jù)包交互提供保證。

  • icmp.c: 包含了ICMP 協(xié)議實(shí)現(xiàn)的相關(guān)函數(shù),ICMP 協(xié)議為IP 數(shù)據(jù)包傳遞過程中的差錯(cuò) 報(bào)告、差錯(cuò)糾正以及目的地址可達(dá)性測試提供了支持,常見的Ping 命令就屬于ICMP 應(yīng)用的 一種

  • igmp.c: 包含了網(wǎng)絡(luò)組管理協(xié)議IGMP 的實(shí)現(xiàn),IGMP 為網(wǎng)絡(luò)中的多播數(shù)據(jù)傳輸提供了 支持,主機(jī)加入某個(gè)多播組后,可以接收到該組的UDP 多播數(shù)據(jù)

  • ip4_addr.c: 實(shí)現(xiàn)了幾個(gè)比較簡單 的IP 地址處理函數(shù),如判斷一個(gè)IP 地址是否為廣播地址的函數(shù),以及32 位IP 地址與點(diǎn)分十 進(jìn)制地址間的轉(zhuǎn)換函數(shù)等

  • ip4_frag.c: 提供了IP 層數(shù)據(jù)包分片與重組相關(guān)的函數(shù)的實(shí)現(xiàn)。

  • Ip4.c: 包含了IPv4 協(xié)議實(shí)現(xiàn)的相關(guān)函數(shù),如數(shù)據(jù)包的接收、遞交、發(fā)送等

  • ipv6目錄: 包含了IPv6 標(biāo)準(zhǔn)中和IP層數(shù)據(jù)包處理相關(guān)的所有代碼

  • mld6.c: IPv6的多播偵聽器發(fā)現(xiàn)。旨在符合RFC 2710。

  • nd6.c: IPv6的鄰居發(fā)現(xiàn)和無狀態(tài)地址自動配置。 旨在符合RFC 4861(鄰居發(fā)現(xiàn))和RFC 4862(地址自動配置)。

  • Iinet6.c: 目前沒有啥實(shí)際內(nèi)容。

  • 其他文件與IPv4目錄下的功能相同,不過是在IPv6版上的實(shí)現(xiàn)

  • def.c: 文件包含了IP 層使用到的一些功能函數(shù)的定義,如IP 地址的轉(zhuǎn)換、網(wǎng)絡(luò)字節(jié)序與 主機(jī)字節(jié)序轉(zhuǎn)換等

  • dns.c: 實(shí)現(xiàn)了DNS 客戶端的所有代碼,DNS 稱為域名系統(tǒng),通常用戶要訪問某個(gè)外 部的主機(jī)時(shí),可能只知道該主機(jī)的名字,而不知道該主機(jī)的IP 地址。常理也是這樣,用戶可 以簡單地記得某個(gè)主機(jī)的名字,如www.baidu.com,卻很難記得這個(gè)主機(jī)的IP 地址。通過使 用DNS,可以解決這個(gè)問題,通過訪問DNS 服務(wù)器,我們可以得到與主機(jī)名對應(yīng)的IP 地址, 這為用戶的使用帶來了方便。值得指出的是,DNS 也是一個(gè)上層應(yīng)用程序,它通?;赨DP 來傳輸數(shù)據(jù)。

  • inet_chksum.c: 這些是校驗(yàn)和算法的一些參考實(shí)現(xiàn),其目標(biāo)是簡單,正確和完全便攜。 Checksumming是您希望為您的平臺優(yōu)化的第一件事。 如果您創(chuàng)建自己的版本,請將其鏈接到cc.h中

  • init.c: 主要包含了一個(gè)與LwIP 協(xié)議棧初始化密切相關(guān)的函數(shù),以及一些 協(xié)議棧配置信息的檢查與輸出

  • ip.c: IPv4和IPv6共用的代碼。

  • mem.c: 包含了協(xié)議棧內(nèi)存堆管理函數(shù)的實(shí)現(xiàn)。

    (1)LwIP 支持的動態(tài)內(nèi)存管理機(jī)制主要有三種:C庫自帶內(nèi)存分配策略(malloc/free/realloc)、動態(tài)內(nèi)存堆(Heap)分配策略、動態(tài)內(nèi)存池(pool)分配策略。
    (2)此文件即LwIP實(shí)現(xiàn)的動態(tài)內(nèi)存堆(Heap)分配策略。
    (3)默認(rèn)不使用C庫自帶內(nèi)存分配策略。 在lwipopts.h使用宏值MEM_LIBC_MALLOC = 1選擇使用C庫自帶內(nèi)存分配策略

  • memp.c: 包含了協(xié)議棧內(nèi)存池管理函數(shù)的實(shí)現(xiàn)。

    (1)LwIP 支持的動態(tài)內(nèi)存管理機(jī)制主要有三種:C庫自帶內(nèi)存分配策略(malloc/free/realloc)、動態(tài)內(nèi)存堆(HEAP)分配策略、動態(tài)內(nèi)存池(POOL)分配策略。
    (2)此文件即LwIP實(shí)現(xiàn)的動態(tài)內(nèi)存池(POOL)分配策略
    (3)默認(rèn)不使用動態(tài)內(nèi)存堆(HEAP)分配策略。 在lwipopts.h使用宏值MEMP_MEM_MALLOC = 1選擇使用動態(tài)內(nèi)存堆(HEAP)分配策略

  • netif.c: 包含了協(xié)議棧網(wǎng)絡(luò)接口管理的相關(guān)函數(shù),協(xié)議棧支持多個(gè)網(wǎng)絡(luò)接口,例如以太網(wǎng)接口、SLIP接口等,協(xié)議棧內(nèi)部對每個(gè)接口用一個(gè)對應(yīng)的netif數(shù)據(jù)結(jié)構(gòu)進(jìn)行描述,并通過使用netif.c中的函數(shù)進(jìn)行統(tǒng)一管理。同時(shí),netif.c還包含了環(huán)回接口管理和數(shù)據(jù)處理的相關(guān)函數(shù),使用環(huán)回接口可以實(shí)現(xiàn)同一主機(jī)上兩個(gè)應(yīng)用程序之間的數(shù)據(jù)交換。

  • pbuf.c: 包含了協(xié)議棧內(nèi)核使用的數(shù)據(jù)包管理函數(shù),數(shù)據(jù)包pbuf管理的實(shí)現(xiàn)是整個(gè)協(xié)議棧中很有特色的地方,采用特殊的數(shù)據(jù)包pbuf 結(jié)構(gòu),可以避免數(shù)據(jù)在各個(gè)層次之間遞交時(shí)的拷貝,這既提高了數(shù)據(jù)遞交效率,也節(jié)省了內(nèi)存空間。

  • raw.c: 為應(yīng)用層提供了一種直接和IP 數(shù)據(jù)包交互的方式,這類似于Socket 編程中原始套接字的概念,它同TCP、UDP 處于同一等級,享受IP 層提供的服務(wù)。使用原始套接字, 可以直接讀取IP 層接收到的數(shù)據(jù)包,例如ICMP 包、UDP 包等,也可以自行構(gòu)造ping包等, 為用戶的程序編寫提供了很大的方便。這是LwIP最底層的API部分。使用這一級別的api進(jìn)行編程需要對TCP/IP相當(dāng)了解。

  • stats.c: 包含了協(xié)議棧內(nèi)部數(shù)據(jù)統(tǒng)計(jì)與顯示的相關(guān)函數(shù),如內(nèi)存使用狀況、郵箱、信號量等信息。

  • sys.c: 實(shí)現(xiàn)了一個(gè)簡單的函數(shù)void sys_msleep(u32_t ms);,它借助操作系統(tǒng)模擬層的信號量機(jī)制完成睡眠一定時(shí)間的功能,該函數(shù)主要在PPP 中使用。前面曾提到過,若需要使用協(xié)議棧的Sequential API和Socket API,則必須使用底層操作系統(tǒng)提供的郵箱與信號量機(jī)制,這時(shí)內(nèi)核要求移植者提供一個(gè)稱為sys_arch.c的操作系統(tǒng)模擬層文件,該文件主要完成對操作系統(tǒng)中郵 箱與信號量函數(shù)的封裝。需要注意,只有在提供文件sys_arch.c 的基礎(chǔ)上,文件`sys.c 才有效,換句話說,在無操作系統(tǒng)環(huán)境下運(yùn)行LwIP 時(shí),sys.c文件都不會被編譯。

  • tcp_in.c: 包含了TCP 協(xié)議中數(shù)據(jù)接收、處理相關(guān)的函數(shù),最重要的TCP 狀態(tài)機(jī)函數(shù)也在這個(gè)文件中

  • tcp_out.c: 包含了TCP 中數(shù)據(jù)發(fā)送相關(guān)的函數(shù),例如數(shù)據(jù)包發(fā)送函數(shù)、超時(shí)重傳函數(shù)等。

  • tcp: 包含了對TCP 控制塊操作的函數(shù),也包括了TCP 定時(shí)處理函數(shù)

  • timeouts.c: 統(tǒng)一完成了對內(nèi)核各個(gè)協(xié)議定時(shí)事件處理函數(shù)的封裝,同時(shí)對各個(gè)注冊的定時(shí)事件進(jìn)行處理。在有無操作系統(tǒng)模擬層的環(huán)境下,timeouts.c 采用不同的方法來實(shí)現(xiàn)定時(shí):在無操作系統(tǒng)模擬層時(shí),timeouts.c使用系統(tǒng)時(shí)鐘函數(shù)sys_now(不同的平臺的都需要移植該函數(shù))來獲得當(dāng)前系統(tǒng)時(shí)間,從而可以判斷出各個(gè)事件是否超時(shí);在有操作系統(tǒng)模擬層時(shí),timers.c 實(shí)現(xiàn)了對操作系統(tǒng)模擬層郵箱等待函數(shù)的再次封裝,得到一個(gè)具有協(xié)議棧特色的郵箱操作函數(shù)。 所謂特色,就是在郵箱等待函數(shù)中加入一種機(jī)制,在郵箱上等待消息的同時(shí),可以同時(shí)實(shí)現(xiàn)協(xié)議棧中各個(gè)定時(shí)事件的正確處理。

    在2.0.0之前的版本中,該文件名為timer.c。新的timeouts.c對原來的內(nèi)容進(jìn)行了一定的封裝,簡化。

  • udp.c: 包含了實(shí)現(xiàn)UDP 協(xié)議的相關(guān)函數(shù),包括UDP 控制塊管理、UDP 數(shù)據(jù)包發(fā)送函數(shù)、UDP 數(shù)據(jù)包接收函數(shù)等

include目錄

LwIP使用的各種頭文件。與各源碼目錄相對應(yīng)。

  • netif文件夾: 主要是針對netif目錄中源文件的各種頭文件。
  • posix文件夾: 主要是針對POSIX標(biāo)準(zhǔn),進(jìn)行的封裝,里面的文件非常簡單,基本都是對外部的引用。
  • lwip文件夾: LwIP的各種頭文件,其中需要注意的有opt.h 文件,它包含了所有LwIP內(nèi)核參數(shù)的默認(rèn)配置值;還有init.h 文件,它包含了與當(dāng)前 LwIP 源代碼信息相關(guān)的宏定義,如協(xié)議版本號、是否為官方版等。
  • apps文件夾: 主要是針對源碼中 app目錄的各頭文件。
  • priv文件夾: LwIP內(nèi)部使用的頭文件,禁止外部使用
  • prot文件夾: 這個(gè)文件夾中主要是針對TCP/IP規(guī)約的各種定義。與netif文件夾中同名文件區(qū)別在于netif文件夾中的文件均為對外提供的API,本目錄才是對規(guī)約層各種結(jié)構(gòu)的定義。

netif目錄

??該目錄下主要包含通用網(wǎng)絡(luò)接口設(shè)備驅(qū)動程序。實(shí)現(xiàn)最底層的相關(guān)協(xié)議,該部分的多數(shù)源碼基本已經(jīng)到了最底層和硬件直接打交道了。

  • ppp文件夾: 包含了PPP 協(xié)議實(shí)現(xiàn)的源代碼。PPP 協(xié)議即點(diǎn)對點(diǎn)協(xié)議,它提供了 一種在點(diǎn)對點(diǎn)線路上傳輸多協(xié)議數(shù)據(jù)包的標(biāo)準(zhǔn)格式,PPP 協(xié)議為鏈路的建立、控制與認(rèn)證提供 了標(biāo)準(zhǔn)。起初PPP 主要用來替代SLIP 這種簡單的串行鏈路數(shù)據(jù)傳輸協(xié)議,但是由于其完整的認(rèn)證機(jī)制,后來在以太網(wǎng)上也引入了PPP 機(jī)制,即PPPoE,它已成為近年來小區(qū)寬帶撥號上網(wǎng)的主要方式。使用PPPoE,為用戶的上網(wǎng)計(jì)費(fèi)、配置、接入等提供了方便。LwIP 提供了對PPPoE 的支持,在ppp文件夾下的PPPoE.c文件中有相關(guān)的函數(shù)實(shí)現(xiàn)。
  • ethernet.c: 以太網(wǎng)接口的共享代碼。目前就兩個(gè)函數(shù):用來從網(wǎng)卡接收以太網(wǎng)數(shù)據(jù)包的函數(shù)和在網(wǎng)卡上發(fā)送以太網(wǎng)數(shù)據(jù)包的函數(shù)。
  • ethernetif.c : 包含了與以太網(wǎng)網(wǎng)卡密切相關(guān)的初始化、發(fā)送、接收等函數(shù)的實(shí)現(xiàn)。注意:這個(gè)文件夾中的函數(shù)并不能使用, 它們都是一個(gè)框架性的結(jié)構(gòu), 移植者需要根據(jù)自己使用的網(wǎng) 卡特性來完成這些函數(shù)。
  • slipif.c: 和 ethernetif.c 很相似,SLIP即串行鏈路IP,它提供了一種在串行鏈路上傳送IP 數(shù)據(jù)包的函數(shù)定義。SLIP 協(xié)議比較簡單,它只是定義了一系列的字符,以實(shí)現(xiàn)對鏈路上的IP數(shù)據(jù)包封裝和發(fā)送,除此之外,它不提供任何尋址、錯(cuò)誤檢測、包類型識別機(jī)制,因此相關(guān)驅(qū)動程序的實(shí)現(xiàn)也比較簡單。它需要一個(gè)sio(串行I / O)模塊才能工作。移植者需要根據(jù)自己使用的串行線路特性(如串口)來實(shí)現(xiàn)以下這些函數(shù)(通常在另一個(gè)文件中,不要直接修改該文件):
    • u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
    • u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len);
    • void sio_send(u8_t c, sio_fd_t fd);
    • sio_fd_t sio_open(u8_t devnum);
  • lowpan6.c: 6LoWPAN協(xié)議的實(shí)現(xiàn)文件。6LoWPAN是一種基于IPv6的低速無線個(gè)域網(wǎng)標(biāo)準(zhǔn),即IPv6 over IEEE 802.15.4。

移植說明

??LWIP 的手動移植可以說非常麻煩,需要我們自己實(shí)現(xiàn)好多文件。最主要的是,需要實(shí)現(xiàn)的文件還沒有個(gè)統(tǒng)一的說明,必須要東拼西湊! LWIP 的移植由兩部分組成,分別為 LWIP 協(xié)議棧和 contrib 應(yīng)用實(shí)例 。目前,這兩部分是由兩個(gè)獨(dú)立的版本庫控制,并且由不同的人來負(fù)責(zé)的(好消息是從2.1.x之后,這倆要合并了)!我們在移植使用 LWIP 時(shí),需要從官網(wǎng)分別下載這兩部分的源代碼!

其中,contrib 中是一些和平臺移植相關(guān)的代碼以及一些使用 LWIP 實(shí)現(xiàn)的應(yīng)用,在移植時(shí)非常有用;LWIP 則是 TCP/IP 協(xié)議棧的核心源碼!綜上所述,LwIP 的移植主要分為以下這些部分:

  • 運(yùn)行環(huán)境的搭建: 有其需要注意的是,針對嵌入式的移植時(shí),無論哪種模式,都需要首先需要處理硬件資源,例如在 STM32Fx 系列芯片移植時(shí),需要提供文件:stm32f4x7_eth_bsp.c/h,已處理使用的硬件資源。當(dāng)然,如果是在 Windows 上做測試使用,則沒有這一步。
  • 源代碼文件的整理: 主要就是東拼西湊LWIP需要的文件(LWIP需要用戶實(shí)現(xiàn)很多文件)
  • LwIP 的基本配置: 根據(jù)自己的需要來配置功能
  • 與 CPU 或編譯器相關(guān)源文件: LWIP 需要用戶的文件之一
  • 與操作系統(tǒng)的接口源文件(僅在系統(tǒng)模式下使用): LWIP 需要用戶的文件之一
  • 與底層網(wǎng)卡驅(qū)動的接口源文件。: LWIP 需要用戶的文件之一
  • 初始化 LwIP,然后正常使用各功能即可。:

源碼文件整理

??源代碼文件的整理需要注意目錄結(jié)構(gòu),因?yàn)?LWIP 源碼的頭文件的包含路徑是包含路徑的。否則我們就必須更改LWIP 的源代碼!整理完成基本就是以下這個(gè)結(jié)構(gòu):

LWIP │ lwipopts.h /* 這四個(gè)文件屬于用戶文件,每個(gè)用戶可能是不同的,通常放在用戶自己的目錄*/ │ perf.c │ sys_arch.c | ethernetif.c ├─arch /* 這個(gè)需要我們自己建立目錄,存放以下頭文件!注意,根據(jù)平臺,以下文件并不是全部都需要 */ │ bpstruct.h │ cc.h │ cpu.h │ epstruct.h │ perf.h │ sys_arch.h └─lwip /* 這個(gè)目錄下就是 LWIP 源碼目錄下的 src 目錄中的所有文件!根據(jù)功能需要,里面的部分文件其實(shí)是可以不需要的 */├─api├─apps├─core├─include└─netif

??lwIP 可以用于兩種基本模式:主循環(huán)模式(通過配置 NO_SYS == 1,在目標(biāo)系統(tǒng)上運(yùn)行沒有 OS/RTOS)或OS 模式(TCPIP 線程,目標(biāo)系統(tǒng)上有一個(gè)操作系統(tǒng))。在兩種模式下的移植時(shí)區(qū)別還是很大的!

  • Mainloop Mode: 即裸機(jī)下的死循環(huán)模式。在主循環(huán)模式下,只能使用回調(diào)式 API(Raw API)。需要確保確保在 lwIP 中一次只有一個(gè)執(zhí)行環(huán)境。
  • OS Mode: 此時(shí),使用者需要提供一個(gè)名為sys_arch.c/h 的文件。因?yàn)樵谙到y(tǒng)模式下,LwIP 需要系統(tǒng)的信號量、郵箱隊(duì)列等。LWIP 提供了這兩個(gè)文件的模板,用戶只需要在模板文件中進(jìn)行實(shí)現(xiàn)各預(yù)定義的接口即可。

第一步:LwIP的基本配置

LwIP 的配置主要通過文件 lwipopts.h 實(shí)現(xiàn),移植時(shí)需要根據(jù)自己的需要,進(jìn)行相關(guān)的配置,然后在自己的項(xiàng)目中添加該文件。一個(gè)在 STM32F4 芯片移植是的配置文件如下:

/********************************************************************************* @file lwipopts.h* @author MCD Application Team* @version V1.1.0* @date 31-July-2013* @brief lwIP Options Configuration.* This file is based on Utilities\lwip_v1.4.1\src\include\lwip\opt.h * and contains the lwIP configuration for the STM32F4x7 demonstration.******************************************************************************* @attention** <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>** Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");* You may not use this file except in compliance with the License.* You may obtain a copy of the License at:** http://www.st.com/software_license_agreement_liberty_v2** Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.********************************************************************************/#ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__/*** SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain* critical regions during buffer allocation, deallocation and memory* allocation and deallocation.*/ #define SYS_LIGHTWEIGHT_PROT 0#define ETHARP_TRUST_IP_MAC 0 #define IP_REASSEMBLY 0 #define IP_FRAG 0 #define ARP_QUEUEING 0/*** NO_SYS==1: Provides VERY minimal functionality. Otherwise,* use lwIP facilities.*/ #define NO_SYS 0/* ---------- Memory options ---------- */ /* MEM_ALIGNMENT: should be set to the alignment of the CPU for whichlwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2byte alignment -> define MEM_ALIGNMENT to 2. */ #define MEM_ALIGNMENT 4/* MEM_SIZE: the size of the heap memory. If the application will send a lot of data that needs to be copied, this should be set high. */ #define MEM_SIZE (5*1024)/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the applicationsends a lot of data out of ROM (or other static memory), thisshould be set high. */ #define MEMP_NUM_PBUF 100 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. Oneper active UDP "connection". */ #define MEMP_NUM_UDP_PCB 6 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCPconnections. */ #define MEMP_NUM_TCP_PCB 10 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCPconnections. */ #define MEMP_NUM_TCP_PCB_LISTEN 5 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCPsegments. */ #define MEMP_NUM_TCP_SEG 20 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously activetimeouts. */ #define MEMP_NUM_SYS_TIMEOUT 10/* ---------- Pbuf options ---------- */ /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #define PBUF_POOL_SIZE 20/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ #define PBUF_POOL_BUFSIZE 500/* ---------- TCP options ---------- */ #define LWIP_TCP 1 #define TCP_TTL 255/* Controls if TCP should queue segments that arrive out oforder. Define to 0 if your device is low on memory. */ #define TCP_QUEUE_OOSEQ 0/* TCP Maximum segment size. */ #define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) *//* TCP sender buffer space (bytes). */ #define TCP_SND_BUF (5*TCP_MSS)/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at leastas much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */#define TCP_SND_QUEUELEN (4* TCP_SND_BUF/TCP_MSS)/* TCP receive window. */ #define TCP_WND (2*TCP_MSS)/* ---------- ICMP options ---------- */ #define LWIP_ICMP 1/* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration ofinterfaces. DHCP is not implemented in lwIP 0.5.1, however, soturning this on does currently not work. */ #define LWIP_DHCP 1/* ---------- UDP options ---------- */ #define LWIP_UDP 1 #define UDP_TTL 255/* ---------- Statistics options ---------- */ #define LWIP_STATS 0 #define LWIP_PROVIDE_ERRNO 1/* ---------- link callback options ---------- */ /* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface* whenever the link changes (i.e., link down)*/ #define LWIP_NETIF_LINK_CALLBACK 1/*------------------------------------------------ Checksum options ------------------------------------------------ *//* The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:- To use this feature let the following define uncommented.- To disable it and process by CPU comment the the checksum. */ /* 注意:校驗(yàn)和可以選擇 由硬件來處理。如果硬件支持該功能,則加載其配置文件(其中需要定義 CHECKSUM_BY_HARDWARE ) */ #include "stm32f4x7_eth_conf.h" #ifdef CHECKSUM_BY_HARDWARE /* 如果芯片的配置中開啟了硬件處理校驗(yàn)和,則對LwIP進(jìn)行配置 *//* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/#define CHECKSUM_GEN_IP 0/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/#define CHECKSUM_GEN_UDP 0/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/#define CHECKSUM_GEN_TCP 0 /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/#define CHECKSUM_CHECK_IP 0/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/#define CHECKSUM_CHECK_UDP 0/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/#define CHECKSUM_CHECK_TCP 0/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/#define CHECKSUM_GEN_ICMP 0 #else/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/#define CHECKSUM_GEN_IP 1/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/#define CHECKSUM_GEN_UDP 1/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/#define CHECKSUM_GEN_TCP 1/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/#define CHECKSUM_CHECK_IP 1/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/#define CHECKSUM_CHECK_UDP 1/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/#define CHECKSUM_CHECK_TCP 1/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/#define CHECKSUM_GEN_ICMP 1 #endif/*-------------------------------------------------------- Sequential layer options -------------------------------------------------------- */ /*** LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)*/ #define LWIP_NETCONN 1/*---------------------------------------------- Socket options ---------------------------------------------- */ /*** LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)*/ #define LWIP_SOCKET 0/*--------------------------------------------- DEBUG options --------------------------------------------- */ #define LWIP_DEBUG 0/*------------------------------------------- OS options ------------------------------------------- */#define TCPIP_THREAD_NAME "TCP/IP" #define TCPIP_THREAD_STACKSIZE 1000 #define TCPIP_MBOX_SIZE 5 #define DEFAULT_UDP_RECVMBOX_SIZE 2000 #define DEFAULT_TCP_RECVMBOX_SIZE 2000 #define DEFAULT_ACCEPTMBOX_SIZE 2000 #define DEFAULT_THREAD_STACKSIZE 500 #define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2) #define LWIP_COMPAT_MUTEX 1#define LWIP_COMPAT_MUTEX_ALLOWED 1#endif /* __LWIPOPTS_H__ *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

第二步:與 CPU 或編譯器相關(guān)接口

??與 CPU 或編譯器相關(guān)的源文件,主要包括數(shù)據(jù)長度,字的高低位順序,編譯器對c語言中struct結(jié)構(gòu)字節(jié)對齊問題(c語言中struct結(jié)構(gòu)是四字節(jié)對對齊的,但lwip中是根據(jù)struct結(jié)構(gòu)中不同數(shù)據(jù)的長度來讀取數(shù)據(jù)的)。主要有以下文件組成(僅僅是個(gè)例子,實(shí)際不一定有全部文件):

??上圖例子中,處理了針對目前主流的編譯器(VC、ARMCC、IAR等)的各種宏定義,比較全面,文件也比較多。自己在移植時(shí)文件個(gè)數(shù)/名字可能不同。但是最基本的cc.h、perf.h、sys_arch.h是 LwIP 規(guī)定的文件名,必須一致。

第三步:與操作系統(tǒng)的接口源文件

??LwIP為了適應(yīng)不同的操作系統(tǒng),在代碼中沒有使用和某一個(gè)操作系統(tǒng)相關(guān)的系統(tǒng)調(diào)用和數(shù)據(jù)結(jié)構(gòu)。而是在LwIP和操作系統(tǒng)之間增加了一個(gè)操作系統(tǒng)封裝層。操作系統(tǒng)封裝層為操作系統(tǒng)服務(wù)(定時(shí),進(jìn)程同步,消息傳遞)提供了一個(gè)統(tǒng)一的接口。在Lwip中進(jìn)程同步使用semaphone和消息傳遞采用"mbox"。
??因此,使用者必須根據(jù)自己使用的系統(tǒng),完成sys_arch.h 和sys_arch.c這兩個(gè)文件。關(guān)于這個(gè)文件,在LwIP源碼的doc/sys_arch.txt有詳細(xì)的說明。當(dāng)然,如果在裸機(jī)下使用,則不需要該步驟。

注意:
無論是否有系統(tǒng),其中有個(gè)函數(shù)sys_now都必須被提供,具體可參見 LwIP 之 sys_arch

第四步:與底層網(wǎng)卡驅(qū)動的接口源文件

??該部分主要是針對文件ethernetif.c和slipif.c。移植時(shí),需要根據(jù)自己使用的網(wǎng)卡或者串行鏈路修改/實(shí)現(xiàn)內(nèi)部的各函數(shù)。

ethernetif.c

??LwIP的網(wǎng)絡(luò)驅(qū)動有一定的模型,/src/netif/ethernetif.c文件即為驅(qū)動的模版,用戶為自己的網(wǎng)絡(luò)設(shè)備實(shí)現(xiàn)驅(qū)動時(shí)應(yīng)參照此模塊。在 LwIP中可以有多個(gè)網(wǎng)絡(luò)接口,每個(gè)網(wǎng)絡(luò)接口都對應(yīng)了一個(gè)struct netif。這個(gè)netif包含了相應(yīng)網(wǎng)絡(luò)接口的屬性、收發(fā)函數(shù)。

slipif.c

??和ethernetif.c很相似,SLIP即串行鏈路IP,它提供了一種在串行鏈路上傳送IP 數(shù)據(jù)包的函數(shù)定義。SLIP 協(xié)議比較簡單,它只是定義了一系列的字符,以實(shí)現(xiàn)對鏈路上的IP數(shù)據(jù)包封裝和發(fā)送,除此之外,它不提供任何尋址、錯(cuò)誤檢測、包類型識別機(jī)制,因此相關(guān)驅(qū)動程序的實(shí)現(xiàn)也比較簡單。它需要一個(gè)sio(串行I / O)模塊才能工作。 移植者需要根據(jù)自己使用的串行線路特性(如串口)來實(shí)現(xiàn)以下這些函數(shù)(通常在另一個(gè)文件中,不要直接修改該文件):

  • u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
  • u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len);
  • void sio_send(u8_t c, sio_fd_t fd);
  • sio_fd_t sio_open(u8_t devnum);

通常,在移植時(shí)不會使用該文件。

第五步:初始化LwIP

??在處理完以上需要移植的個(gè)文件后,接下來就可以在自己的項(xiàng)目中建立初始化函數(shù)來對LwIP進(jìn)行初始化了,以下為使用系統(tǒng)時(shí)的一個(gè)初始化例子。

void LwIP_Init(void) {ip_addr_t ipaddr;ip_addr_t netmask;ip_addr_t gw; #ifdef USE_DHCPuint8_t iptab[4] = {0};uint8_t iptxt[20]; #endif/* 創(chuàng)建tcp_ip線程,初始化LwIP的各部分 */tcpip_init(NULL, NULL);/* 設(shè)置IP地址等信息 */ #ifdef USE_DHCPipaddr.addr = 0;netmask.addr = 0;gw.addr = 0; #elseIP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); #endif/* 以下就是添加網(wǎng)絡(luò)接口了 *//* - netif_add(struct netif *netif, 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))Adds your network interface to the netif_list. Allocate a structnetif and pass a pointer to this structure as the first argument.Give pointers to cleared ip_addr structures when using DHCP,or fill them with sane numbers otherwise. The state pointer may be NULL.The init function pointer must point to a initialization function foryour ethernet netif interface. The following code illustrates it's use.*/netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);/* Registers the default network interface.*/netif_set_default(&xnetif);if (EthStatus == (ETH_INIT_FLAG | ETH_LINK_FLAG)){/* Set Ethernet link flag */xnetif.flags |= NETIF_FLAG_LINK_UP;/* When the netif is fully configured this function must be called.*/netif_set_up(&xnetif);#ifdef USE_DHCPDHCP_state = DHCP_START;#endif /* USE_DHCP */}else{/* When the netif link is down this function must be called.*/netif_set_down(&xnetif);#ifdef USE_DHCPDHCP_state = DHCP_LINK_DOWN;#endif /* USE_DHCP */}/* Set the link callback function, this function is called on change of link status*/netif_set_link_callback(&xnetif, ETH_link_callback); }

??首先看以下tcpip_init函數(shù),該函數(shù)負(fù)責(zé)建立tcp_ip線程,并且初始化LwIP的各部分功能,具體看以下圖片。

??設(shè)置IP地址這塊沒啥可說的,接下來就是添加網(wǎng)絡(luò)接口,具體參見 LwIP 之 ethernetif.c。

總結(jié)

以上是生活随笔為你收集整理的LwIP 之一 源码目录文件详解及移植说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。