国产无码免费,人妻口爆,国产V在线,99中文精品7,国产成人无码AA精品一,制度丝袜诱惑av,久久99免费麻辣视频,蜜臀久久99精品久久久久久酒店
        訂閱
        糾錯
        加入自媒體

        Linux內核源代碼:tcp/ip協議棧的調用

        2021-06-21 10:33
        一口Linux
        關注

        這里共維護了三個隊列:prequeue、backlog、receive_queue,分別為預處理隊列,后備隊列和接收隊列,在連接建立后,若沒有數據到來,接收隊列為空,進程會在sk_busy_loop函數內循環等待,知道接收隊列不為空,并調用函數數skb_copy_datagram_msg將接收到的數據拷貝到用戶態,實際調用的是__skb_datagram_iter,這里同樣用了struct msghdr *msg來實現。__skb_datagram_iter函數如下:

        int __skb_datagram_iter(const struct sk_buff *skb, int offset,
        struct iov_iter *to, int len, bool fault_short,
                   size_t (*cb)(const void *, size_t, void *, struct iov_iter *),
                   void *data)

        int start = skb_headlen(skb);
        int i, copy = start - offset, start_off = offset, n;
        struct sk_buff *frag_iter;
        拷貝tcp頭部
        if (copy > 0) {
        if (copy > len)
        copy = len;
               n = cb(skb->data + offset, copy, data, to);
               offset += n;
        if (n != copy)
        goto short_copy;
        if ((len -= copy) == 0)
        return 0;
           }
        拷貝數據部分
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
        int end;
        const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
               WARN_ON(start > offset + len);
               end = start + skb_frag_size(frag);
        if ((copy = end - offset) > 0) {
        struct page *page = skb_frag_page(frag);
                   u8 *vaddr = kmap(page);
        if (copy > len)
        copy = len;
                   n = cb(vaddr + frag->page_offset +
                       offset - start, copy, data, to);
                   kunmap(page);
                   offset += n;
        if (n != copy)
        goto short_copy;
        if (!(len -= copy))
        return 0;
               }
               start = end;
           }

        拷貝完成后,函數返回,整個接收的過程也就完成了。
        用一張函數間的相互調用圖可以表示:

        通過gdb調試驗證如下:

        Breakpoint 1, __sys_recvfrom (fd=5, ubuf=0x7ffd9428d960, size=1024, flags=0,
        addr=0x0 <fixed_percpu_data>, addr_len=0x0 <fixed_percpu_data>)
        at net/socket.c:1990
        1990    {
        (gdb) c
        Continuing.
        Breakpoint 2, sock_recvmsg (sock=0xffff888006df1900, msg=0xffffc900001f7e28,
        flags=0) at net/socket.c:891
        891    {
        (gdb) c
        Continuing.
        Breakpoint 3, tcp_recvmsg (sk=0xffff888006479100, msg=0xffffc900001f7e28,
        len=1024, nonblock=0, flags=0, addr_len=0xffffc900001f7df4)
        at net/ipv4/tcp.c:1933
        1933    {
        (gdb) cBreakpoint 1, __sys_recvfrom (fd=5, ubuf=0x7ffd9428d960, size=1024, flags=0,
        addr=0x0 <fixed_percpu_data>, addr_len=0x0 <fixed_percpu_data>)
        at net/socket.c:1990
        1990    {
        (gdb) c
        Continuing.
        Breakpoint 2, sock_recvmsg (sock=0xffff888006df1900, msg=0xffffc900001f7e28,
        flags=0) at net/socket.c:891
        891    {
        (gdb) c
        Continuing.
        Breakpoint 3, tcp_recvmsg (sk=0xffff888006479100, msg=0xffffc900001f7e28,
        len=1024, nonblock=0, flags=0, addr_len=0xffffc900001f7df4)
        at net/ipv4/tcp.c:1933
        1933    {
        (gdb) c
        Continuing.
        Breakpoint 4, __skb_datagram_iter (skb=0xffff8880068714e0, offset=0,
        to=0xffffc900001efe38, len=2, fault_short=false,
        cb=0xffffffff817ff860 <simple_copy_to_iter>, data=0x0 <fixed_percpu_data>)
        at net/core/datagram.c:414
        414    {

        符合我們之前的分析。

        5 IP層流程

        5.1 發送端

        網絡層的任務就是選擇合適的網間路由和交換結點, 確保數據及時傳送。網絡層將數據鏈路層提供的幀組成數據包,包中封裝有網絡層包頭,其中含有邏輯地址信息- -源站點和目的站點地址的網絡地址。其主要任務包括 (1)路由處理,即選擇下一跳 (2)添加 IP header(3)計算 IP header checksum,用于檢測 IP 報文頭部在傳播過程中是否出錯 (4)可能的話,進行 IP 分片(5)處理完畢,獲取下一跳的 MAC 地址,設置鏈路層報文頭,然后轉入鏈路層處理。

        IP 頭:

        IP 棧基本處理過程如下圖所示:

        首先,ip_queue_xmit(skb)會檢查skb->dst路由信息。如果沒有,比如套接字的第一個包,就使用ip_route_output()選擇一個路由。

        接著,填充IP包的各個字段,比如版本、包頭長度、TOS等。

        中間的一些分片等,可參閱相關文檔。基本思想是,當報文的長度大于mtu,gso的長度不為0就會調用 ip_fragment 進行分片,否則就會調用ip_finish_output2把數據發送出去。ip_fragment 函數中,會檢查 IP_DF 標志位,如果待分片IP數據包禁止分片,則調用 icmp_send()向發送方發送一個原因為需要分片而設置了不分片標志的目的不可達ICMP報文,并丟棄報文,即設置IP狀態為分片失敗,釋放skb,返回消息過長錯誤碼。

        接下來就用 ip_finish_ouput2 設置鏈路層報文頭了。如果,鏈路層報頭緩存有(即hh不為空),那就拷貝到skb里。如果沒,那么就調用neigh_resolve_output,使用 ARP 獲取。

        具體代碼分析如下:

        入口函數是ip_queue_xmit,函數如下:

        發現調用了__ip_queue_xmit函數:

        發現調用了skb_rtable函數,實際上是開始找路由緩存,繼續看:

        發現調用ip_local_out進行數據發送:

        發現調用__ip_local_out函數:

        發現返回一個nf_hook函數,里面調用了dst_output,這個函數實質上是調用ip_finish__output函數:

        發現調用__ip_finish_output函數:

        如果分片就調用ip_fragment,否則就調用IP_finish_output2函數:

        在構造好 ip 頭,檢查完分片之后,會調用鄰居子系統的輸出函數 neigh_output 進行輸 出。neigh_output函數如下:

        輸出分為有二層頭緩存和沒有兩種情況,有緩存時調用 neigh_hh_output 進行快速輸 出,沒有緩存時,則調用鄰居子系統的輸出回調函數進行慢速輸出。這個函數如下:

        最后調用dev_queue_xmit函數進行向鏈路層發送包,到此結束。gdb驗證如下:

        5.2 接收端

        IP 層的入口函數在 ip_rcv 函數。該函數首先會做包括 package checksum 在內的各種檢查,如果需要的話會做 IP defragment(將多個分片合并),然后 packet 調用已經注冊的 Pre-routing netfilter hook ,完成后最終到達 ip_rcv_finish 函數。

        ip_rcv_finish 函數會調用 ip_router_input 函數,進入路由處理環節。它首先會調用 ip_route_input 來更新路由,然后查找 route,決定該 package 將會被發到本機還是會被轉發還是丟棄:

        如果是發到本機的話,調用 ip_local_deliver 函數,可能會做 de-fragment(合并多個 IP packet),然后調用 ip_local_deliver 函數。該函數根據 package 的下一個處理層的 protocal number,調用下一層接口,包括 tcp_v4_rcv (TCP), udp_rcv (UDP),icmp_rcv (ICMP),igmp_rcv(IGMP)。對于 TCP 來說,函數 tcp_v4_rcv 函數會被調用,從而處理流程進入 TCP 棧。

        如果需要轉發 (forward),則進入轉發流程。該流程需要處理 TTL,再調用 dst_input 函數。該函數會

        (1)處理 Netfilter Hook

        (2)執行 IP fragmentation

        (3)調用 dev_queue_xmit,進入鏈路層處理流程。

        接收相對簡單,入口在ip_rcv,這個函數如下:

        里面調用ip_rcv_finish函數:

        發現調用dst_input函數,實際上是調用ip_local_deliver函數:

        如果分片,就調用ip_defrag函數,沒有則調用ip_local_deliver_finish函數:

        發現調用ip_protocol_deliver_rcu函數:

        調用完畢之后進入tcp棧,調用完畢,通過gdb驗證如下:

        <上一頁  1  2  3  4  下一頁>  余下全文
        聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

        發表評論

        0條評論,0人參與

        請輸入評論內容...

        請輸入評論/評論長度6~500個字

        您提交的評論過于頻繁,請輸入驗證碼繼續

        暫無評論

        暫無評論

          人工智能 獵頭職位 更多
          掃碼關注公眾號
          OFweek人工智能網
          獲取更多精彩內容
          文章糾錯
          x
          *文字標題:
          *糾錯內容:
          聯系郵箱:
          *驗 證 碼:

          粵公網安備 44030502002758號

          主站蜘蛛池模板: 一级天堂| 91.www| jizzjizz欧美| 欧美精产国品一二三区| 69精品人人人人人| 好吊av| 超碰97人人天天蜜芽| 91福利导航大全| www.jizzjizz| 自贡市| 伊人久久大香线蕉av一区 | 无码人妻一区二区三区线花季传件| 江西省| 天堂无码在线| 中文字幕高清在线观看| 精品九九在线| 狼人久久乐| 91在线观看| 彭水| 91色在线视频| 精品久久久久中文慕人妻| 温泉县| 亚洲精品偷拍| 91免费在线| AV青青草| 91资源在线| 51av视频| freeAV爽视频| 灵丘县| 无码人妻精品一区二区三区温州| 久久中文字幕人妻| 精品xxx| 国产19p| 成人A在线播放| 日韩精品极品视频在线观看免费| 尤物福利导航| 国产AV一区二区三区| 浠水县| 亚洲AV无码久久精品色欲| 丁香婷婷五月| jizz网站|