<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                從前面的章節我們知道,網絡接口(如以太網接口)是硬件接口,(提示:網絡接口又可以稱之為網卡,為了統一,下文均采用網卡表示網絡接口),LwIP是軟件,那么怎么讓硬件與軟件無縫連接起來呢?而且,網卡又有多種多樣,怎么能讓LwIP使用同樣的軟件能兼容不同的硬件呢?原來LwIP使用一個數據結構——netif來描述一個網卡,但是由于網卡是直接與硬件打交道的,硬件不同則處理基本是不同的,所以必須由用戶提供最底層接口函數,LwIP提供統一的接口,但是底層的實現需要用戶自己去完成,比如網卡的初始化,網卡的收發數據,當LwIP底層得到了網絡的數據之后,才會傳入內核中去處理;同理,LwIP內核需要發送一個數據包的時候,也需要調用網卡的發送函數,這樣子才能把數據從硬件接口到軟件內核無縫連接起來。LwIP中的 ethernetif.c文件即為底層接口的驅動的模版,用戶為自己的網絡設備實現驅動時應參照此模塊做修改。ethernetif.c文件中的函數通常為與硬件打交道的底層函數,當有數據需要通過網卡接收或者發送數據的時候就會被調用,經過LwIP協議棧內部進行處理后,從應用層就能得到數據或者可以發送數據。 簡單來說,netif是LwIP抽象出來的網卡,LwIP協議棧可以使用多個不同的接口,而ethernetif.c文件則提供了netif訪問各種不同的網卡,每個網卡有不同的實現方式,用戶只需要修改ethernetif.c文件即可。 在單網卡中,這個netif結構體只有一個,可能還有人會問,那么一個設備中有多個網卡怎么辦,很簡單,LwIP會將每個用netif描述的網卡連接成一個鏈表(單向鏈表),該鏈表就記錄每個網卡的netif。屏蔽硬件接口的差異,完成了對不同網卡的抽象,因此了解netif結構體是移植LwIP的關鍵。 我們可以理解將整個網絡的數據傳輸理解為物流,那么網卡就是不同的運輸工具,我們可以選擇汽車、飛機、輪船等運輸工具,不同的運輸工具速度是不一樣的,但是對于一個物流公司而言,可能同時存在很多種運輸的工具,這就需要物流公司去記錄這些運輸工具,當有一個包裹需要通過飛機運輸出去,那么物流公司就會將這個包裹通過飛機發送出去,這就好比我們的網卡,需要哪個網卡發送或者接收網絡數據的時候,就會讓對應的網卡去工作。 下面一起來看看netif數據結構是怎么樣的,具體見代碼清單 4?1。 ``` 1 struct netif 2 { 3 #if !LWIP_SINGLE_NETIF 4 /* 指向netif鏈表中的下一個 */ 5 struct netif *next; (1) 6 #endif 7 8 #if LWIP_IPV4 9 /* 網絡字節中的IP地址、子網掩碼、默認網關配置 */ 10 ip_addr_t ip_addr; 11 ip_addr_t netmask; 12 ip_addr_t gw; (2) 13 #endif /* LWIP_IPV4 */ 14 15 /* 此函數由網絡設備驅動程序調用,將數據包傳遞到TCP/IP協議棧。 16 * 對于以太網物理層,這通常是ethernet_input()*/ 17 netif_input_fn input; (3) 18 19 #if LWIP_IPV4 20 21 /* 此函數由IP層調用,在接口上發送數據包。通常這個功能, 22 * 首先解析硬件地址,然后發送數據包。 23 * 對于以太網物理層,這通常是etharp_output() */ 24 netif_output_fn output; (4) 25 26 #endif /* LWIP_IPV4 */ 27 /* 此函數由ethernet_output()調用,當需要在網卡上發送一個數據包時。 28 * 底層硬件輸出數據函數,一般是調用自定義函數low_level_output*/ 29 netif_linkoutput_fn linkoutput; (5) 30 31 #if LWIP_NETIF_STATUS_CALLBACK 32 /* 當netif狀態設置為up或down時調用此函數 */ 33 netif_status_callback_fn status_callback; (6) 34 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 35 36 #if LWIP_NETIF_LINK_CALLBACK 37 /* 當netif鏈接設置為up或down時,將調用此函數 */ 38 netif_status_callback_fn link_callback; (7) 39 #endif /* LWIP_NETIF_LINK_CALLBACK */ 40 41 #if LWIP_NETIF_REMOVE_CALLBACK 42 /* 當netif被刪除時調用此函數 */ 43 netif_status_callback_fn remove_callback; (8) 44 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 45 46 /* 此字段可由設備驅動程序設置并指向設備的狀態信息。 47 * 主要是將網卡的某些私有數據傳遞給上層,用戶可以自由發揮,也可以不用。*/ 48 void *state; (9) 49 50 #ifdef netif_get_client_data 51 void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; 52 #endif 53 #if LWIP_NETIF_HOSTNAME 54 /* 這個netif的主機名,NULL也是一個有效值 */ 55 const char* hostname; 56 #endif /* LWIP_NETIF_HOSTNAME */ 57 58 #if LWIP_CHECKSUM_CTRL_PER_NETIF 59 u16_t chksum_flags; 60 #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ 61 62 /** 最大傳輸單位(以字節為單位),對于以太網一般設為 1500 */ 63 u16_t mtu; (10) 64 65 /** 此網卡的鏈路層硬件地址 */ 66 u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; (11) 67 68 /** 硬件地址長度,對于以太網就是 MAC 地址長度,為6字節 */ 69 u8_t hwaddr_len; (12) 70 71 /* 網卡狀態信息標志位,是很重要的控制字段, 72 * 它包括網卡功能使能、廣播使能、 ARP 使能等等重要控制位。 */ 73 u8_t flags; (13) 74 75 /* 字段用于保存每一個網卡的名字。用兩個字符的名字來標識網絡接 76 * 口使用的設備驅動的種類,名字由設備驅動來設置并且應該反映通過網卡 77 * 表示的硬件的種類。比如藍牙設備( bluetooth)的網卡名字可以是 bt, 78 * 而 IEEE 802.11b WLAN 設備的名字就可以是wl,當然設置什么名字用戶是可 79 * 以自由發揮的,這并不影響用戶對網卡的使用。當然,如果兩個網卡 80 * 具有相同的網絡名字,我們就用 num 字段來區分相同類別的不同網卡*/ 81 char name[2]; (14) 82 83 /* 用來標示使用同種驅動類型的不同網卡 */ 84 u8_t num; (15) 85 86 #if MIB2_STATS 87 /* 連接類型 */ 88 u8_t link_type; 89 /* 連接速度 */ 90 u32_t link_speed; 91 /* 最后一次更改的時間戳 */ 92 u32_t ts; 93 /** counters */ 94 struct stats_mib2_netif_ctrs mib2_counters; 95 #endif /* MIB2_STATS */ 96 97 #if LWIP_IPV4 && LWIP_IGMP 98 /** 可以調用此函數來添加或刪除多播中的條目 99 以太網MAC的過濾表。*/ 100 netif_igmp_mac_filter_fn igmp_mac_filter; 101 #endif /* LWIP_IPV4 && LWIP_IGMP */ 102 103 #if LWIP_NETIF_USE_HINTS 104 struct netif_hint *hints; 105 #endif /* LWIP_NETIF_USE_HINTS */ 106 107 #if ENABLE_LOOPBACK 108 /* List of packets to be queued for ourselves. */ 109 struct pbuf *loop_first; 110 struct pbuf *loop_last; 111 112 #if LWIP_LOOPBACK_MAX_PBUFS 113 u16_t loop_cnt_current; 114 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 115 116 #endif /* ENABLE_LOOPBACK */ 117 }; ``` 我們挑一些比較重要的netif字段進行講解: * (1):LwIP使用鏈表來管理同一設備的多個網卡。在netif.c文件中定義兩個全局指針:struct netif *netif_list和struct netif *netif_default,其中netif_list就是網卡鏈表指針,指向網卡鏈表的首節點(第一個網卡),后者表示默認情況下(有多網口時)使用哪個網卡。next字段指向下一個netif結構體指針,在一個設備中有多個網卡時,才使用該字段。 * (2):ip_addr字段記錄的是網絡中的IP地址,netmask字段記錄的是子網掩碼,gw記錄的是網關地址,這些字段是用于描述網卡的網絡地址屬性。 IP地址必須與網卡對應,即設備擁有多少個網卡那就必須有多少個IP地址;子網掩碼可以用來判斷某個IP地址與當前網卡是否處于同一個子網中,IP在發送數據包的時候會選擇與目標IP地址處于同一子網的網卡來發送;網關地址在數據包的發送、轉發過程非常重要,如果要向不屬于同一子網的主機(主機目標IP地址與網卡不屬于同一子網)發送一個數據包,那么LwIP就會將數據包發送到網關中,網關設備會對該數據包進行正確的轉發,除此之外,網關還提供很多高級功能,如DNS,DHCP等。 * (3):input是一個函數指針,指向一個函數,該函數由網絡設備驅動程序調用,將數據包傳遞到TCP/IP協議棧(IP層)。對于以太網物理層,這通常是ethernet_input(),參數為pbuf和netif類型,其中pbuf為接收到的數據包。 * (4):output也是一個函數指針,指向一個函數,此函數由IP層調用,在接口上發送數據包。用戶需要編寫該函數并使output指向它,通這個函數的處理步驟是首先解析硬件地址,然后發送數據包。對于以太網物理層,該函數通常是etharp_output(),參數為pbuf、netif和ip_addr類型,其中,ipaddr代表要將該數據包發送到的地址,但不一定是數據包最終到到達的IP地址,比如,要發送IP數據報到一個并不在本網絡的主機上,該數據包要被發送到一個路由器上,這里的ipaddr就是路由器IP地址。 * (5):linkoutput字段和output類似,也需要用戶自己實現一個函數,但只有兩個參數,它是由ARP模塊調用的,一般是自定義函數low_level_output()。當需要在網卡上發送一個數據包時,該函數會被ethernet_output()函數調用。 * (6):當netif狀態設置為up或down時,將調用此函數。 * (7):當netif連接設置為up或down時,將調用此函數。 * (8):當netif被刪除時調用此函數。 * (9):此字段可由設備驅動程序設置并指向設備的狀態信息。主要是將網卡的某些私有數據傳遞給上層,用戶可以自由發揮,也可以不用。 * (10):最大傳輸單位(以字節為單位),對于以太網一般設為 1500,在IP層發送數據的時候,LwIP會使用該字段決定是否需要對數據包進行分片處理,為什么是在IP層進行分片處理?因為鏈路層不提供任何的差錯處理機制,如果在網卡中接收的數據包不滿足網卡自身的屬性,那么網卡可能就會直接丟棄該數據包,也可能在底層進行分包發送,但是這種分包在IP層看來是不可接受的,因為它打亂了數據的結構,所以只能由IP層進行分片處理。 * (11):此網卡的鏈路層硬件地址。 * (12):硬件地址長度,對于以太網就是 MAC 地址長度,為6字節 * (13):網卡狀態信息標志位,是很重要的控制字段,它包括網卡功能使能、廣播使能、 ARP 使能等等重要控制位。 * (14):name字段用于保存每一個網卡的名字。用兩個字符的名字來標識網卡使用的設備驅動的種類,名字由設備驅動來設置并且應該反映通過網卡表示的硬件的種類。比如藍牙設備(bluetooth)的網卡名字可以是 bt,而 IEEE 802.11b WLAN設備的名字就可以是wl,當然設置什么名字用戶是可以自由發揮的,這并不影響用戶對網卡的使用。當然,如果兩個網卡具有相同的網絡名字,我們就用 num字段來區分相同類別的不同網卡。 * (15):用來標識使用同種驅動類型的不同網卡。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看