freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

linux網(wǎng)絡(luò)設(shè)備分析-資料下載頁

2025-06-29 08:40本頁面
  

【正文】 SE_COUNT。 /* 對應(yīng)于第7項內(nèi)容 */return 0。}由上容易看到,ne_close幾乎就是ne_open在鏡中的像。/* from drivers/net/ */int ei_open(struct device *dev){struct ei_device *ei_local = (struct ei_device *) devpriv。if (ei_local == NULL){ /* 只有沒調(diào)用ethdev_init(),才會出現(xiàn)以下的錯誤 */printk(KERN_EMERG %s: ei_open passed a nonexistent device!\n, devname)。return ENXIO。}irq2dev_map[devirq] = dev。 /* 對應(yīng)于上面所列內(nèi)容的第3項 */NS8390_init(dev, 1)。 /* 下面將分析 */devstart = 1。 /* 對應(yīng)于第6項,表示接口UP */ei_localirqlock = 0。 /* 對應(yīng)于第5項 */return 0。}int ei_close(struct device *dev){NS8390_init(dev, 0)。devstart = 0。 /* 對應(yīng)于第6項內(nèi)容,表示接口DOWN */return 0。}void NS8390_init(struct device *dev, int startp){…………/* 設(shè)置8390的各種寄存器的狀態(tài) */…………devtbusy = 0。devinterrupt = 0。 /* 對應(yīng)于第6項內(nèi)容 */ei_localtx1 = ei_localtx2 = 0。ei_localtxing = 0。 /* 對應(yīng)于第5項內(nèi)容 */…………}另外,文件net/core/,如dev_ifsioc(void *arg, unsigned int getset)它可以處理許多ioctl SIGNAL:讀取和修改接口網(wǎng)絡(luò)地址(對TCP/IP就是IP地址)、讀取和修改接口的devflags、讀取和設(shè)置MTU、讀取和設(shè)置廣播地址等等。ifconfig的功能大部分是通過該文件提供的函數(shù)實(shí)現(xiàn)的。五. 數(shù)據(jù)包的傳輸和接收當(dāng)物理網(wǎng)絡(luò)設(shè)備接收到數(shù)據(jù)時,系統(tǒng)是如何知道并讀取數(shù)據(jù)的呢?當(dāng)前可通過兩種途徑解決這個問題。一種方法是輪詢方式,系統(tǒng)每隔一定的時間間隔就去檢查一次物理設(shè)備,若設(shè)備“報告”說有數(shù)據(jù)到達(dá),就調(diào)用讀取數(shù)據(jù)的程序。在Linux中,輪詢方式可通過定時器實(shí)現(xiàn),但該方法存在一個明顯的缺點(diǎn):不管設(shè)備是否有數(shù)據(jù),系統(tǒng)總是要固定地花CPU時間去查看設(shè)備,且可能延遲對一些緊急數(shù)據(jù)的處理,因?yàn)榫W(wǎng)絡(luò)設(shè)備有數(shù)據(jù)時可能不能馬上得到CPU的響應(yīng)。在這種方式下,設(shè)備完全處于一種被動的狀態(tài),而CPU又負(fù)擔(dān)過重。無論從資源的利用率上還是從效率上看,這種方法都不是最優(yōu)的。另一種方法是中斷方式,中斷方式利用硬件體系結(jié)構(gòu)的中斷機(jī)制實(shí)現(xiàn)設(shè)備和系統(tǒng)的應(yīng)答對話,即當(dāng)物理設(shè)備需要CPU處理數(shù)據(jù)時,設(shè)備就發(fā)一個中斷信號給系統(tǒng),系統(tǒng)則在收到信號后調(diào)用相應(yīng)的中斷服務(wù)程序響應(yīng)對設(shè)備中斷的處理。中斷方式有效地解決了設(shè)備與CPU的對話交流問題,并將CPU從繁重的設(shè)備輪詢中解脫出來,大大提高了CPU的利用率。當(dāng)前不管是Linux平臺還是Windows平臺,它們的網(wǎng)絡(luò)設(shè)備驅(qū)動程序幾乎都是使用中斷方式的。故在此我們主要討論基于中斷方式的網(wǎng)絡(luò)設(shè)備驅(qū)動程序。網(wǎng)絡(luò)分層引起的一個問題是,每層的協(xié)議在發(fā)送數(shù)據(jù)包時要加協(xié)議頭和協(xié)議尾到原數(shù)據(jù)中,在收到數(shù)據(jù)包時則要將本層的協(xié)議頭和協(xié)議尾從數(shù)據(jù)包中去掉。這使得在不同層協(xié)議間傳輸時,每層都需要知道自己這一層的協(xié)議頭和協(xié)議尾在數(shù)據(jù)包的哪里。一種解決方法是在每層都復(fù)制緩沖區(qū),但顯然效率太低。Linux的做法是用一種數(shù)據(jù)結(jié)構(gòu)sk_buff在不同協(xié)議層及網(wǎng)絡(luò)設(shè)備驅(qū)動程序之間傳送數(shù)據(jù)。sk_buff 包括指針和長度域段,允許每個協(xié)議層通過標(biāo)準(zhǔn)的函數(shù)操作傳送的數(shù)據(jù)包。該數(shù)據(jù)結(jié)構(gòu)在整個Linux的網(wǎng)絡(luò)子系統(tǒng)包括網(wǎng)絡(luò)設(shè)備中扮演了一個十分重要的角色,故我們在分析數(shù)據(jù)包的傳輸和接收之前,首先來看看sk_buff這個數(shù)據(jù)結(jié)構(gòu)的內(nèi)容及系統(tǒng)提供的相關(guān)操作。因?yàn)閷υ摂?shù)據(jù)結(jié)構(gòu)的了解將大大有助于對Linux整個網(wǎng)絡(luò)子系統(tǒng)的理解。1. Socket緩沖區(qū)及相關(guān)操作與塊設(shè)備的緩沖區(qū)處理方式不同,網(wǎng)絡(luò)設(shè)備發(fā)送與接收數(shù)據(jù)包用的緩沖區(qū)是一個統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)sk_buff (include/linux/)。對該數(shù)據(jù)結(jié)構(gòu),核心提供了一系列低層的操作函數(shù),從而使該數(shù)據(jù)結(jié)構(gòu)具有網(wǎng)絡(luò)協(xié)議傳輸需要的通常的緩沖功能和流控制能力,并可方便、靈活地處理數(shù)據(jù)包首尾的增加和刪除。右圖是sk_buff結(jié)構(gòu)的一個示意圖,其中每個sk_buff 都帶有一塊數(shù)據(jù)區(qū),并有四個數(shù)據(jù)指針指向相應(yīng)的位置:unsigned char *head。指向被分配的內(nèi)存空間的首地址;unsigned char *data。指向當(dāng)前數(shù)據(jù)包的首地址;unsigned char *tail。指向當(dāng)前數(shù)據(jù)包的末地址;unsigned char *end。指向被分配的內(nèi)存空間的末地址;unsigned long len。當(dāng)前數(shù)據(jù)包的大小。len=skbtail – skbdata;unsigned long truesize分配到的內(nèi)存空間大小。len=skbend – skbhead;由于數(shù)據(jù)包的大小會隨著自己在不同協(xié)議層間的傳送而會不斷地變化,故data和tail指針也將會不斷地改變,即依賴于skb當(dāng)前所在的協(xié)議層;head和end指針則在內(nèi)存空間分配后就固定不變。對緩沖區(qū)的操作,核心提供了一個比較完整的函數(shù)界面,下面將列出用的最多的幾個函數(shù)并作分析說明。/* from net/core/ */struct sk_buff *alloc_skb (unsigned int len, int priority)。struct sk_buff *dev_alloc_skb (unsigned int len)。申請一個sk_buff緩沖區(qū)。alloc_skb函數(shù)分配一個緩沖區(qū)并將skbdata和skbtail初始化為skbhead;dev_alloc_skb函數(shù)是alloc_skb函數(shù)的一個快捷方式,它用priority= GFP_ATOMIC調(diào)用alloc_skb并在skbdata和skbhead之間保留16字節(jié)的空間。這16字節(jié)也用來填寫硬件頭(hardware header)。void kfree_skb (struct sk_buff *skb, int rw)。void dev_kfree_skb (struct sk_buff *skb, int rw)。釋放一個sk_buff緩沖區(qū)。kfree_skb供核心內(nèi)部調(diào)用,驅(qū)動程序應(yīng)該用dev_kfree_skb,因?yàn)樗苷_處理緩沖區(qū)加鎖。參數(shù)rw可用FREE_READ或FREE_WRITE。用于發(fā)送的緩沖區(qū)應(yīng)該用FREE_WRITE,用于接收的則用FREE_READ。unsigned char *skb_put (struct sk_buff *skb, int len)。當(dāng)有數(shù)據(jù)要加到緩沖區(qū)的尾部時,用于增加skbtail和skblen。返回值是修改之前的skbtail指針。unsigned char *skb_push (struct sk_buff *skb, int len)。當(dāng)有數(shù)據(jù)要加到緩沖區(qū)的首部時,用于減少skbdata及增大skblen。返回值是修改之后的skbdata。int skb_tailroom (struct sk_buff *skb)。該函數(shù)返回在sk_buff 中可用于put的空間大小(尾部空余空間)。若緩沖區(qū)被正確分配到空間,驅(qū)動程序通常不需要檢查緩沖區(qū)中空余空間的大小。由于驅(qū)動程序在申請空間之前可得到數(shù)據(jù)包的大小,故只有嚴(yán)重出錯的驅(qū)動程序才會put太多的數(shù)據(jù)到緩沖區(qū)中。int skb_headroom (struct sk_buff *skb)。類似于skb_tailroom,該函數(shù)返回可用的push的空間大小,即首部空余空間。void skb_reserve (struct sk_buff *skb, int len)。該函數(shù)既增加skbdata又增加skbtail,即在首部留出len大小的空間。在填充緩沖區(qū)之前,可用該函數(shù)保留一部分首部空間。許多以太網(wǎng)卡在首部保留2字節(jié)空間,這樣在14字節(jié)的以太網(wǎng)頭的后面,IP頭就能以16字節(jié)對齊了。unsigned char *skb_pull (struct sk_buff *skb, int len)。從數(shù)據(jù)包的頭部剔除數(shù)據(jù)。它減少skblen并增加skbdata。以太網(wǎng)的頭就是這樣從接收到的數(shù)據(jù)包中被剔除的。void skb_trim(struct sk_buff *skb, int len)從數(shù)據(jù)包的尾部剔除數(shù)據(jù)。它將skblen設(shè)為len,并改變skbtail。2. 數(shù)據(jù)包的傳輸由于網(wǎng)絡(luò)分層的原因,當(dāng)用戶要傳輸數(shù)據(jù)時,數(shù)據(jù)包是沿著網(wǎng)絡(luò)協(xié)議由上往下逐層下傳的。如本文開頭的網(wǎng)絡(luò)設(shè)備工作原理圖所示,最后,數(shù)據(jù)包將通過dev_queue_xmit()[net/core/]函數(shù)傳送給網(wǎng)絡(luò)接口。網(wǎng)絡(luò)接口的任務(wù)就是將數(shù)據(jù)包傳送給硬件,讓物理網(wǎng)絡(luò)設(shè)備完成最終的物理傳輸。從device結(jié)構(gòu)中我們可以看到,每個網(wǎng)絡(luò)接口都應(yīng)有一個叫devhard_start_xmit的硬件傳輸函數(shù)指針,Linux正是通過這個函數(shù)指針來完成實(shí)際的數(shù)據(jù)傳輸?shù)摹S布鬏敽瘮?shù)hard_start_xmit函數(shù)的一般流程如下:1. 通過標(biāo)志位tbusy判斷上次數(shù)據(jù)包的傳輸是否完成。若tbusy=0就做下一步;否則,看上次傳輸是否已超時,若未超時,就不成功返回,若已超時,則初始化芯片寄存器、置tbusy=0,然后繼續(xù)下一步;2. 將tbusy標(biāo)志位打開;3. 將數(shù)據(jù)包傳給硬件發(fā)送;4. 釋放緩沖區(qū)skb;5. 修改接口的一些統(tǒng)計信息。由上幾節(jié)對NE2000的分析,我們可以發(fā)現(xiàn),該網(wǎng)絡(luò)設(shè)備的傳輸函數(shù)devhard_start_xmit為ei_start_xmit()。下面我們將繼續(xù)以NE2000為例,對網(wǎng)絡(luò)接口的數(shù)據(jù)傳輸過程進(jìn)行分析。在本文中分析時,作者試圖盡量避免依賴于硬件的那一部分代碼,以便加深對整個網(wǎng)絡(luò)設(shè)備管理機(jī)制的把握,并試圖強(qiáng)調(diào)、突出一般網(wǎng)絡(luò)設(shè)備所共有的東西。/* from drivers/net/ drivers/net/ *//* 傳輸函數(shù) */static int ei_start_xmit(struct sk_buff *skb, struct device *dev){ int e8390_base = devbase_addr。 struct ei_device *ei_local = (struct ei_device *) devpriv。 int length, send_length, output_page。 /* 若設(shè)備忙,就判斷上次傳輸是否已超時 */ if (devtbusy) { /* 讀取傳輸狀態(tài)寄存器的值 */ int txsr = inb(e8390_base+EN0_TSR), isr。 /* EN0_TSR 傳輸狀態(tài)寄存器(讀)*/ int tickssofar = jiffies devtrans_start。 /* define TX_TIMEOUT (20*HZ/100) */ if (tickssofar TX_TIMEOUT || (tickssofar (TX_TIMEOUT+5) amp。amp。 ! (txsr amp。 ENTSR_PTX))) { return 1。 /* 未超時,或超時一點(diǎn)點(diǎn)且發(fā)送時出錯 */ } /* 已超時 */ ………… /* 重新初始化芯片寄存器 */ ei_reset_8390(dev)。 NS8390_init(dev, 1)。 /* 將開始傳輸域段置為的當(dāng)前時間坐標(biāo)點(diǎn) */ devtrans_start = jiffies。 } ………… /* 屏蔽網(wǎng)絡(luò)設(shè)備的硬件中斷 */ outb_p(0x00, e8390_base + EN0_IMR)。 /* EN0_IMR 中斷屏蔽寄存器(WR)*/ if (devinterrupt) { /* 正在運(yùn)行中斷服務(wù)程序 */ printk(%s: Tx request while isr active.\n,devname)。/* 恢復(fù)中斷屏蔽,失敗返回; EN0_IMR 中斷屏蔽寄存器(WR)*/ outb_p(ENISR_ALL, e8390_base + EN0_IMR)。 return 1。 } ei_localirqlock = 1。 send_length = ETH_ZLEN length ? length : ETH_ZLEN。 /* 硬件傳輸 */ ei_block_output(dev, length, skbdata, ei_localtx_start_page)。 ei_localtxing = 1。 NS8390_trigger_send(dev, send_length, ei_localtx_start_page)。 /* 設(shè)置開始傳輸時間坐標(biāo)點(diǎn),打開“忙”標(biāo)志 */ devtrans_start = jiffies。 devtbusy = 1。 …………
點(diǎn)擊復(fù)制文檔內(nèi)容
物理相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1