當網路上一台計算機準備傳送資料時,他的網絡卡開始工作了,首先網絡卡的晶元偵聽在網路上是否有資料在
流動,如果沒有,他就把資料傳送到網路上,在偵聽和傳送之間有一段極小的時間延遲,在這段時間內,也有
可能在網路上有其他的計算機也準備傳送資料,也偵聽到網路上沒有資料在流動,這就可能兩台甚至多台
的資料一起傳送到網路上,產生資料的碰撞,傳送資料的計算機的網絡卡晶元當然要在傳送完成後再校驗返回
的資料,如果發現和傳送的資料不一致,那就是說產生了碰撞,所以在乙個以太網路中的計算機數量不宜過多,
他不但會增加廣播包在網路中的數量,也請也會增加資料報的碰撞次數.
我們的計算機的網絡卡晶元在接收到一完整的資料報後,晶元的一引腳通知8259中斷控制器,中斷控制器再
發出中斷給cpu,由此,cpu隨即呼叫該網絡卡的中斷例程,如:
dos是這樣的
遮蔽所有中斷(cli)
push any register
因為中斷向量在段0
所以xor ax,ax
mov ds,ax
mul ax,中斷號
那麼在資料段的[ax]偏移處是該中斷例程的指標了
call [ax]就到該中斷例程了
...(dos是比較遙遠的事情了,我所描述的是他的原理,當然不會這麼簡單,如果那位網友有興趣詳細描述一下
上面的原理,糾正或替換掉我所寫的就感激不盡了)
總之,在本例程中,cpu將呼叫elintr中斷例程,並帶有引數unit即該種網絡卡的第幾塊(因為在計算機中,你有可能
裝了相同的網絡卡有幾塊),elintr的作用是把資料從網絡卡的資料儲存器中讀到我們在該網絡卡初始化時預先分配好
的資料緩衝區中,他呼叫的函式就只有elread,同樣elread也只呼叫了elget乙個函式.elread函式比較簡單,就是
呼叫elget,elget則相對比較複雜一點,涉及到核心記憶體分配mbuf,mbuf是比較恐怖的東西,正如steven所寫的,為
了節約當時"巨大"的4m記憶體,犧牲了效能搞出了這個mbuf東東,mbuf是必須要弄懂的,雖然在裝置驅動程式中呼叫
他的巨集和函式不多,但在後面的ip協議,tcp協議中有不少涉及的地方.
關於資料傳送方面和接收差不多,在上層協議放置好資料到mbuf鏈後,呼叫el_start函式,該函式把mbuf鏈中
的資料放置到本塊網絡卡的傳送佇列緩衝el_pktbuf中,然後再呼叫el_xmit函式,此函式把傳送佇列緩衝el_pktbuf
中的資料有傳遞到網絡卡的資料儲存器中.我認為,這中間的記憶體拷貝是多於的,應該在el_start函式中直接把mbuf
中的資料傳遞到網絡卡的資料儲存器中,這樣會使效能有較大幅度的提公升,因為在驅動程式設計時,最好減少大量的
記憶體拷貝,他占用的時間太多了.
*//* freebsd的3com乙太網裝置驅動程式 */
/*本段標頭檔案是在編譯核心時產生的*/
*/top = 0;
mp = &
while (totlen > 0)
m->m_len = mlen;/*非鏈首mbuf的長度為mlen,這個if(top)就代表不是鏈首mbuf*/
}/*如果跳過了上面哪個if,那肯定是鏈的第乙個mbuf,並且m已經在迴圈外就分配好了.*/
len = min(totlen, epkt - cp);/*epkt在計算後指向資料的尾部,cp指向首部*/
if (len >= minclsize) else else
len = m->m_len;
}bcopy(cp, mtod(m, caddr_t), (unsigned)len);/*第一次資料移動,費時的操作*/
cp += len;
*mp = m;
mp = &m->m_next;/*把mbuf鏈結起來*/
totlen -= len;
if (cp == epkt)
cp = buf;
}return (top);/*返回裝填資料的mbuf鏈首*/
}/*總結:在該函式中,所做的事情非常費時,主要是做記憶體的申請,大批資料的拷貝,如果象nfs傳送資料,會出現大量的簇的申請和大量
簇的資料的拷貝,一次迴圈需要拷貝2048個32位的雙字.如果是發給本機的,那還行,如果是本機做為橋**及防活牆,即資料不上傳
到ip層處理,那麼可以直接改寫mbuf的分配方案,根據不同的網路流量可初始化一定數量的大容量的緩衝鏈(可以以乙個乙太網的整
頁數來分配,如是100m乙太網是1514位元組,可分配2048位元組,是有一點浪費,但效能可提高,sc->el_pktbuf可變為一佇列,用來和其他
網絡卡的接收佇列進行資料交換.這意味著光資料進入就少拷貝一次,效能將大大提高,目前我正在研究中.)*/
/** 處理乙個ioctl請求.
*/static int
el_ioctl(ifp, command, data)
register struct ifnet *ifp;
u_long command; /*ioctl的命令*/
caddr_t data;
else
break;
default:
error = einval;
}(void) splx(s);
return (error);
}/* 一般是資料在規定的時間內沒有發出後被呼叫的程式,目前該驅動程式不支援 */
static void
el_watchdog(struct ifnet *ifp)
網絡卡驅動程式
1 網路子系統 如下的核心空間的幾層 使用者空間 應用層 核心空間 系統呼叫 通過socket訪問網路子系統 核心空間 協議無關介面 一組通用函式通過socket訪問不同協議 核心空間 網路協議層 各種傳輸層網路層協議tcp udp ip 核心空間 裝置無關介面 核心空間 裝置驅動 硬體裝置 2 網...
網絡卡驅動程式
我們這裡說的是網絡卡驅動程式,不是網路驅動程式,網路有七層,我們寫的只是最底層的東西,網路這麼多層,但是最終你還是要操作硬體啊 所以上面肯定有個硬體相關層,我們要寫的就是硬體相關的驅動程式這一小塊。網絡卡你不需要開啟什麼裝置,你只需要socket程式設計就行了 怎麼寫1 分配某個結構體 2 設定 3...
Linux網絡卡驅動程式分析
學習應該是乙個先把問題簡單化,再把問題複雜化的過程。一開始就著手處理複雜的問題,難免讓人有心驚膽顫,捉襟見肘的感覺。讀linux網絡卡驅動 也是一樣。那長長的原始碼夾雜著那些我們陌生的變數和符號,望而生畏便是理所當然的了。不要擔心,事情總有解決的辦法,先把一些我們管不著的 切割出去,留下必須的部分,...