自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux網(wǎng)絡(luò)包從中斷到接收的一生

系統(tǒng) Linux
如果在虛擬化環(huán)境下,VMM配置GIC ITS (Interrupt Translation Service) ,建立物理中斷與虛擬中斷的映射完成中斷虛擬化使得網(wǎng)卡能直接向VM發(fā)出中斷,同時(shí)通過(guò)IO虛擬化,網(wǎng)卡通過(guò)IOMMU將packet直接寫(xiě)入虛擬機(jī)內(nèi)核的rx_ring

 [[333072]]

 

Linux網(wǎng)絡(luò)包從中斷到接收的一生

 

linux

既然要講,那就把一個(gè)包的整個(gè)包生都說(shuō)了算了

觸發(fā)中斷

  • 在非虛擬化環(huán)境下,網(wǎng)卡通過(guò)DMA將packet寫(xiě)入內(nèi)核的rx_ring環(huán)形隊(duì)列緩沖區(qū),并觸發(fā)中斷。
  • 如果在虛擬化環(huán)境下,VMM配置GIC ITS (Interrupt Translation Service) ,建立物理中斷與虛擬中斷的映射完成中斷虛擬化使得網(wǎng)卡能直接向VM發(fā)出中斷,同時(shí)通過(guò)IO虛擬化,網(wǎng)卡通過(guò)IOMMU將packet直接寫(xiě)入虛擬機(jī)內(nèi)核的rx_ring

Top Half

  • CPU在收到中斷之后,調(diào)用網(wǎng)卡ISR也就是所謂的中斷handler
  • 分配sk_buf并入input_pkt_queue(如果隊(duì)列已滿則丟棄)
  • 發(fā)出一個(gè)軟中斷NET_RX_SOFTIRQ,軟中斷可以被調(diào)度例如通過(guò)tasklet

Bottom Half

  • sk_buf從input_pkt_queue傳入process_queue,根據(jù)協(xié)議類型調(diào)用網(wǎng)絡(luò)層協(xié)議的handler
  • ip_rcv執(zhí)行包頭檢查,ip_router_input()進(jìn)行路由,決定本機(jī)/轉(zhuǎn)發(fā)/丟棄
  • tcp_v4_rcv執(zhí)行包頭檢查,tcp_v4_lookup查詢對(duì)應(yīng)的socket和connection,如果正常,tcp_prequeue將skb放進(jìn)socket接收隊(duì)列
  • socket隨即喚醒所在的進(jìn)程

 

Linux網(wǎng)絡(luò)包從中斷到接收的一生

 

kqueue

因?yàn)閑poll沒(méi)有論文,就說(shuō)說(shuō)kqueue是怎么做的吧,kqueue會(huì)根據(jù)socket綁定的knote鏈表(每個(gè)監(jiān)聽(tīng)的kqueue都可能創(chuàng)建一個(gè)knote),將knote通過(guò)反向指針獲得kqueue,將knote加入kqueue的就緒隊(duì)列末尾。如果此時(shí)恰好有進(jìn)程正在監(jiān)聽(tīng)的話,將會(huì)喚醒進(jìn)程,kqueue會(huì)被掃描,并從就緒隊(duì)列處獲得所有的event,從而了解已經(jīng)就緒的所有socket。

  • 喚醒的進(jìn)程調(diào)用socket recv系統(tǒng)調(diào)用,如果是TCP則調(diào)用tcp_recvmsg從sk_buffer拷貝數(shù)據(jù)

Batch

  1. netif_receive_skb_list() 

Linux的NAPI還會(huì)繼續(xù)延遲軟中斷的處理,等待其積累足夠的skb后進(jìn)行輪詢,一次性處理所有的skb。

SKB

skb并不是直接存儲(chǔ)報(bào)文,而是存儲(chǔ)指針,指針只需要移動(dòng),就能完成解包,而本身的報(bào)文并不需要修改。上一層的協(xié)議棧會(huì)在處理當(dāng)前層的同時(shí)設(shè)置好下一層的頭指針,并且移動(dòng)data指針。與此同時(shí),skb本身是雙向鏈表實(shí)現(xiàn)的隊(duì)列。qlen為鏈表元素長(zhǎng)度,lock為添加元素時(shí)的鎖。

 

Linux網(wǎng)絡(luò)包從中斷到接收的一生

 

skb結(jié)構(gòu)

談到指針的用法,這里舉個(gè)做OS lab時(shí)印象深刻的奇淫巧技,也是C的指針變態(tài)的地方

  1. #define list_entry(ptr, type, field) \ 
  2.     container_of(ptr, type, field) 
  3. #define container_of(ptr, type, field) \ 
  4.     ((type *)((void *)(ptr) - (u64)(&(((type *)(0))->field)))) 

(u64)(&(((type *)(0))->field))))指的是field在結(jié)構(gòu)體type中的偏移量,通過(guò)減去這個(gè)偏移量我們就能找出某個(gè)對(duì)象所在上級(jí)type對(duì)象的地址,也就是container。

一般來(lái)說(shuō),我們都會(huì)使用下面這樣的方式,讓鏈表節(jié)點(diǎn)去包裹數(shù)據(jù)。

  1. struct page_list_node { 
  2.         struct page p; 
  3.     struct list_node *prev; 
  4.     struct list_node *next
  5. }; 

但是,通過(guò)指針操作,卻可以讓數(shù)據(jù)去包裹鏈表節(jié)點(diǎn)

  1. struct list_head { 
  2.     struct list_head *prev; 
  3.     struct list_head *next
  4. }; 
  5.  
  6. struct page{ 
  7.     struct list_head      list_node; 

在僅僅知道鏈表節(jié)點(diǎn)的情況下,借助成員偏移量即可知道容器對(duì)象的位置并取出

  1. list_entry(somenode,struct page,list_node); 

list_head本身可以存在于任何對(duì)象上,而他們的entry卻能根據(jù)參數(shù)而指向不同的類型,感覺(jué)有點(diǎn)泛型的味道了。

內(nèi)容來(lái)自SJTU,IPADS OS-16-Network

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2021-08-06 22:43:54

中斷架構(gòu)傳遞

2015-04-23 08:51:53

2018-01-18 09:05:05

存儲(chǔ)數(shù)據(jù)包分層

2015-08-03 09:33:21

PH程序員一生

2016-08-24 11:13:30

2023-01-10 08:20:55

RocketMQ消息源碼

2017-03-28 13:25:14

Linux網(wǎng)絡(luò)數(shù)據(jù)包

2020-10-29 15:05:31

Linux網(wǎng)絡(luò)包代碼

2018-01-05 12:42:01

Lisa電腦蘋(píng)果Mac

2020-11-29 17:08:50

程序員IT

2012-12-04 10:08:16

2015-03-24 13:39:08

IE

2021-09-28 08:05:56

黑客網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊

2014-10-11 11:35:49

2012-04-16 09:24:49

程序員

2016-01-25 13:22:45

SparkSparkSQL數(shù)據(jù)分析

2021-12-28 18:23:49

Java指令

2010-01-07 09:32:19

2017-04-11 17:22:57

編程程序員語(yǔ)言

2019-06-26 08:45:28

程序員思考腦年終獎(jiǎng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)