欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
深入剖析網(wǎng)絡(luò )發(fā)送過(guò)程 - 驅動(dòng)開(kāi)發(fā) - Linux論壇
在TCP協(xié)議上,當通過(guò)三方握手建立了連接之后,就進(jìn)入數據包的實(shí)質(zhì)發(fā)送階段,在本文中以send命令來(lái)闡述。當通過(guò)send將數據包發(fā)送之后,glibc函數庫會(huì )啟用另外一個(gè)其定義的別用名函數__libc_sendto(),該函數最后會(huì )間接執行到sendto系統調用:
inline_syscall##nr(name, args);// ##nr說(shuō)明是該系統調用帶有nr個(gè)args參數sendto系統調用的參數值是6,而name就是sendto
從上面的分析可以看出glibc將要執行的下面一條語(yǔ)句是
inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)
在該函數中一段主要功能實(shí)現代碼如下:
__asm__ __volatile__                                    \
          ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"            \
           : inline_syscall_r0_out_constraint (_sc_0),          \
             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
             "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)           \
           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
             "1"(_sc_19), "5"(_sc_20), "6"(_sc_21)              \
           : inline_syscall_clobbers);                          \
        _sc_ret = _sc_0, _sc_err = _sc_19;  
該代碼采用了嵌入匯編(詳細介紹查閱嵌入匯編相關(guān)書(shū)籍),其中:
_sc_0=sendto;
_sc_19 --_sc_21分別是arg1—arg6;
inline_syscall_r0_out_constraint:功能相當于"=r",選用一個(gè)寄存器來(lái)存儲輸出變量。
"0"--"6"分別是%0--%6,代表_sc_0--_sc_21
接下來(lái)函數最終通過(guò)Linux中頂頂有名的INT 0X80陷入系統核心。具體的過(guò)程可以參考內核相關(guān)書(shū)籍。下面是一個(gè)兄弟對INT 0X80的簡(jiǎn)要介紹:
http://blog.chinaunix.net/u2/65427/showart_712571.html
在陷入系統內核以后,最終會(huì )調用系統所提供的系統調用函數sys_sendto(),該函數直接調用了__sock_sendmsg(),該函數對進(jìn)程做一個(gè)簡(jiǎn)單的權限檢查之后就觸發(fā)套接字(socket)中定義的虛擬sendmsg的函數,進(jìn)而進(jìn)入到下一層傳輸層處理。

Layer 4: 傳輸層(Transport Layer)

由上層的討論可知,系統觸發(fā)了sendmsg虛擬接口函數,其實(shí)就是傳輸層中的tcp_sendmsg或是udp_sendmsg,看你所使用的協(xié)議而定。本文介紹tcp_sendmsg().
該函數需要做如下工作:
1)        為sk_buff(后面簡(jiǎn)稱(chēng)skb)分配空間,該函數首先嘗試在套接字緩沖隊列中尋找空閑空間,如果找不到就使用tcp_alloc_pskb()為其重新分配空間。
2)        下面這步就會(huì )tcp_sendmsg函數的主要部分了,將數據拷貝到緩沖區。它分為如下兩種情況:
2.1)如果skb還有剩余空間的話(huà),就使用skb_add_data()來(lái)向skb尾部添加數據包。代碼如下:
if (skb_tailroom(skb) > 0) {
                                /* We have some space in skb head. Superb! */
                                if (copy > skb_tailroom(skb))
                                        copy = skb_tailroom(skb);
                                if ((err = skb_add_data(skb, from, copy)) != 0)
                                        goto do_fault;
                        }
2.2)如果skb沒(méi)有了可用空間,內核會(huì )使用TCP_PAGE宏來(lái)為發(fā)送的數據包分配一個(gè)高速緩存頁(yè)空間,當該頁(yè)被正確地分配后就調用Copy_from_user(to(page地址),from(usr空間),n)將用戶(hù)空間數據包復制到page所在的地址空間。
但是我們都知道數據包在協(xié)議層之間的傳輸是通過(guò)skb的,難道將數據包復制到這個(gè)新分配的page中,內核就可以去睡大覺(jué)了嗎?當然不是!接下來(lái)內核就要來(lái)處理這個(gè)問(wèn)題了,那么怎樣來(lái)處理呢?
此時(shí)就需要使用到skb中的另外一個(gè)數據區struct skb_shared_info[],但是該數據區在創(chuàng )建skb時(shí)是沒(méi)有為其分配空間的,也就是說(shuō)它開(kāi)始純粹就是個(gè)指針,而沒(méi)有具體的告訴它要指向什么地方。這時(shí)大家應該知道它可以指向什么地方了,對,就是page!在內核中對這種情況的具體是通過(guò)fill_page_desc(struct sk_buff *skb,int I,struct page *page,int off,int size)來(lái)實(shí)現的,代碼如下:
static inline void fill_page_desc(struct sk_buff *skb, int i,
                                  struct page *page, int off, int size)
{
        skb_frag_t *frag = &skb_shinfo(skb)->frags;
        frag->page = page;
        frag->page_offset = off;
        frag->size = size;
        skb_shinfo(skb)->nr_frags = i + 1;
}
這里需要注意的是struct skb_shared_info[]只能通過(guò)skb_shinfo來(lái)獲取,在該結構體中skb_flag_t類(lèi)型的flags就是具體指向page的數組。
2.3)至此skb數據包的裝載工作算是結束了,接下來(lái)就需要做一些后續工作,包括是否要分片,以及后來(lái)的TCP協(xié)議頭的添加。先看在tcp_sendmsg()中的最后一個(gè)重要函數tcp_push,它的調用格式如下:
static inline void tcp_push(struct sock *sk, struct tcp_opt *tp, int flags,
                            int mss_now, int nonagle)
細心的朋友會(huì )發(fā)現,在該函數中傳輸的竟然不是skb,而是一個(gè)名為sock的結構體,那這又是什么東東呢?個(gè)人理解是它在頂層協(xié)議層之間(例如:應用層和傳輸層之間)的傳輸起著(zhù)非常重要的作用,相當于溝通兩層之間的紐帶。再深入查找下該結構體的構成,我們很容易發(fā)現這樣一個(gè)結構體變量:struct sk_buff_head,有名稱(chēng)我們可以知道它是用來(lái)描述skb頭部信息的一個(gè)結構體,它指向了buffer的數據區。這下我們也明白了點(diǎn),這個(gè)結構體其實(shí)還充當了一個(gè)隊列作用,是用來(lái)存儲skb的數據區。協(xié)議層之間傳輸完之后,具體到該層處理時(shí)內核就會(huì )從sk_buff_head逐個(gè)中取出skb數據區來(lái)處理,例如添加協(xié)議頭等。
好了,tcp_sendmsg到此結束了它的使命了,下面將要需要的一個(gè)函數就是在tcp_push()中直接用到的一個(gè)函數:__tcp_push_pending_frames(),該函數又直接調用tcp_write_xmit()函數來(lái)進(jìn)一步對數據包處理,它包括一下兩步:
1)        檢查是否需要對數據包進(jìn)行分片,條件是只要skb中全部數據長(cháng)度大于當前路由負荷量就需要分片。
2)        采用skb_clone(skb,GFP_ATOMIC)為T(mén)CP_HEAD分配一個(gè)sk_buff空間,這里需要注意的是skb_clone分配空間的特點(diǎn),它首先是依照參數skb來(lái)來(lái)復制出一個(gè)新的sk_buff,新的skb和舊的skb共享數據變量緩存區,但是結構體緩沖區不是共享的,這似乎和copy on write機制有些相似。
3)        在分配了一個(gè)新的skb之后,內核就會(huì )執行tcp_transmit_skb().其實(shí)內核中是將2,3步合在一起的,如下:
tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC))
接下來(lái)就是tcp_transmit_skb函數的實(shí)現過(guò)程了。
1)        通過(guò)skb_push()在skb前面加入tcp協(xié)議頭信息。這包括序列號,源地址,目的地址,校驗和等。
2)        通過(guò)tcp_opt結構體(它是在該函數的開(kāi)始部分從sock結構體中獲得的)來(lái)訪(fǎng)問(wèn)tcp_func結構體中的.queue_xmit虛擬功能函數,在IPV4中是調用了ip_queue_xmit(),這樣就進(jìn)入了下一層——網(wǎng)絡(luò )層。

未貼完,完整版在附件中。
關(guān)于驅動(dòng)程序部分的聲明:
由于本人沒(méi)有實(shí)際開(kāi)發(fā)過(guò)驅動(dòng)程序,都是看了別人的驅動(dòng)程序之后的體會(huì )和總結,所以難免會(huì )有錯誤,請各位不嗇賜教!
接收過(guò)程待續。。。。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
深入分析原始套接口
十年碼農內功:網(wǎng)絡(luò )發(fā)包詳細過(guò)程(一)
25 張圖,一萬(wàn)字,拆解 Linux 網(wǎng)絡(luò )包發(fā)送過(guò)程
Linux 下網(wǎng)絡(luò )性能優(yōu)化方法簡(jiǎn)析
深入Linux內核網(wǎng)絡(luò )堆棧
TCP/IP學(xué)習(28)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久