【正文】
skb_pull() 把sk_buff緩沖區(qū)里Data area中的空間移一部分到Head room中。 | Tail room(free) | After alloc_skb() | Head room | Tail room(free) | After skb_reserve() | Head room | Data area | Tail room(free) | After skb_put() |Head| skb_ | Data | Tail room(free) | |room| push | | | | | Data area | | After skb_push() | Head | skb_ | Data area | Tail room(free) | | | pull | | | | Head room | | | After skb_pull() 中斷共享Linux系統(tǒng)運行幾個設備共享同一個中斷。需要共享的話,在申請的時候指明共享方式。系統(tǒng)提供的request_irq()調(diào)用的定義: int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id)。如果共享中斷,irqflags設置SA_SHIRQ屬性,這樣就允許別的設備申請同一個 中斷。需要注意所有用到這個中斷的設備在調(diào)用request_irq()都必須設置這個屬 性。系統(tǒng)在回調(diào)每個中斷處理程序時,可以用dev_id這個參數(shù)找到相應的設備。一 般dev_id就設為device結(jié)構(gòu)本身。系統(tǒng)處理共享中斷是用各自的dev_id參數(shù)依次調(diào)用每一個中斷處理程序?!∮布l(fā)送忙時的處理主CPU的處理能力一般比網(wǎng)絡發(fā)送要快,所以經(jīng)常會遇到系統(tǒng)有數(shù)據(jù)要發(fā),但 上一包數(shù)據(jù)網(wǎng)絡設備還沒發(fā)送完。因為在Linux里網(wǎng)絡設備驅(qū)動程序一般不做數(shù)據(jù) 緩存,不能發(fā)送的數(shù)據(jù)都是通知系統(tǒng)發(fā)送不成功,所以必須要有一個機制在硬件不 忙時及時通知系統(tǒng)接著發(fā)送下面的數(shù)據(jù)。一般對發(fā)送忙的處理在前面設備的發(fā)送方法(hard_start_xmit)里已經(jīng)描述過, 即如果發(fā)送忙,置tbusy為1。處理完發(fā)送數(shù)據(jù)后,在發(fā)送結(jié)束中斷里清tbusy,同時用mark_bh()調(diào)用通知系統(tǒng)繼續(xù)發(fā)送。但在具體實現(xiàn)我的驅(qū)動程序時發(fā)現(xiàn),這樣的處理系統(tǒng)好象并不能及時地知道硬件已經(jīng)空閑了,即在mark_bh()以后,系統(tǒng)要等一段時間才會接著發(fā)送。造成發(fā)送效率很低。2M線路只有10%不到的使用率。我最后的實現(xiàn)是不把tbusy置1,讓系統(tǒng)始終認為硬件空閑,但是報告發(fā)送不成功。系統(tǒng)會一直嘗試重發(fā)。這樣處理就運行正常了。但是遍循內(nèi)核源碼中的網(wǎng)絡驅(qū)動程序,似乎沒有這樣處理的。不知道癥結(jié)在哪里?!×髁靠刂?flow control)網(wǎng)絡數(shù)據(jù)的發(fā)送和接收都需要流量控制。這些控制是在系統(tǒng)里實現(xiàn)的,不需要驅(qū)動程序做工作。每個設備數(shù)據(jù)結(jié)構(gòu)里都有一個參數(shù)devtx_queue_len,這個參數(shù)標明發(fā)送時最多緩存的數(shù)據(jù)包。在Linux系統(tǒng)里以太網(wǎng)設備(10/100Mbps)tx_queue_len一般設置為100,串行線路(異步串口)為10。實際上如果看源碼可以知道,設置了devtx_queue_len并不是為緩存這些數(shù)據(jù)申請了空間。這個參數(shù)只是在收到協(xié)議層的數(shù)據(jù)包時判斷發(fā)送隊列里的數(shù)據(jù)是不是到了tx_queue_len的限度,以決定這一包數(shù)據(jù)加不加進發(fā)送隊列。發(fā)送時另一個方面的流控是更高層協(xié)議的發(fā)送窗口(TCP協(xié)議里就有發(fā)送窗口)。達到了窗口大小,高層協(xié)議就不會再發(fā)送數(shù)據(jù)。接收流控也分兩個層次。Netif_rx()緩存的數(shù)據(jù)包有限制。另外高層協(xié)議也會有一個最大的等待處理的數(shù)據(jù)量。發(fā)送和接收流控處理在net/core/()和netif_rx()中?!≌{(diào)試很多Linux的驅(qū)動程序都是編譯進內(nèi)核的,形成一個大的內(nèi)核文件。但對調(diào)試 來說,這是相當麻煩的。調(diào)試驅(qū)動程序可以用module方式加載。支持模塊方式的 驅(qū)動程序必須提供兩個函數(shù):int init_module(void)和void cleanup_module(void)。 Init_module()在加載此模塊時調(diào)用,在這個函數(shù)里可以register_netdev()注冊 設備。Init_module()返回0表示成功,返回負表示失敗。Cleanup_module()在驅(qū)動程序被卸載時調(diào)用,清除占用的資源,調(diào)用unregister_netdev()。模塊可以動態(tài)地加載、卸載。,還有kerneld自動加載模塊。手工加載使用insmod命令,卸載用rmmod命令,看內(nèi)核中的模塊用lsmod命令。編譯驅(qū)動程序用gcc,主要命令行參數(shù)DKERNEL DMODULE。并且作為模塊加載的驅(qū)動程序,只編譯成obj形式(加c參數(shù))。編譯好的目標文件放在/lib/modules/,在啟動文件里用insmod加載。Linux程序設計資料可以從網(wǎng)上獲得。這就是開放源代碼的好處。并且沒有什么“未公開的秘密”。我編寫驅(qū)動程序時參閱的主要資料包括:Linux內(nèi)核源代碼 by Michael K. Johnson by Ori Pomerantz by olly in BBS可以選擇一個模板作為開始,內(nèi)核源代碼里有一個網(wǎng)絡驅(qū)動程序的模板,drivers/net/。里面包含了驅(qū)動程序的基本內(nèi)容。這個模板是以以太網(wǎng)設備為對象的,以太網(wǎng)的處理在Linux系統(tǒng)里有特殊“待遇”,所以如果不是以太網(wǎng)設備,有些細節(jié)上要注意,主要在初始化程序里?!?】許海熱等編著.嵌入式系統(tǒng)技術(shù)與應用.【2】王田苗編著.嵌入式系統(tǒng)設計與實例開發(fā).【3】魏忠等編著.嵌入式開發(fā)詳解。北京:電子工業(yè)出版【4】馬忠梅馬廣云徐英慧天澤編著.ARM嵌入式處理器結(jié)構(gòu)與應用基礎.北京航空航天大學出版社,【5】杜春雷編著.ARM體系結(jié)構(gòu)與編程.清華大學出版社,【6】6陳文智等編著.嵌入式系統(tǒng)開發(fā)原理與實踐.清華大學出版社,【7】胡曉軍張愛成編著.USB接口開發(fā)技術(shù).西安電子科技大學出版社,2005.5,l~74【8】皺思軼編著.嵌入式Linux設計與應用.清華大學出版社,2002.1,241—282【9】T_學龍,嵌入式Linux系統(tǒng)設計與應用.清華大學出版社,2001.8,243~358【10】孫天澤袁文菊張海峰編著.嵌入式設計及Linux驅(qū)動開發(fā)指南.基于ARM9處理器,電子工業(yè)出版社