mbuf全稱即memory buffer,即存儲器緩存,在內核中屬於全局支持的范疇。從網絡協議的角度來說,mbuf的主要用處是保存在進程和網絡接口間相互傳遞的用戶數據。當然,在實際使用中,mbuf除了保存用戶數據以外,還需要保存其他各類數據,比如比較常見的網絡報文頭部的源地址與目的地址以及端口信息乃至Socket選項等。
在軟件系統的設計中,存儲器緩存的概念其實應該並不陌生,它在設計理念上有點像對應到硬件中各種Cache的概念,比如CPU與內存之間有Cache,近階段比較流行的SSD硬盤一般也配備Cache,無非是對高性能的要求做的一種層次性的設計。使用內存緩沖區,可以減少進程之間的相互等待時間,降低內存分配的額外負擔。
比如STL的空間配置器的設計上,SGI設計了雙層級配置器,如果需要配置的空間“過小”(小於128bytes)時,直接采用memory pool的管理方式,維護一個小內存的list,專門負責配置和回收。
回到mbuf,從mbuf所承擔的工作來看,mbuf必須像鏈表一樣,在存儲用戶數據的時候作出一些空間上“浪費”的犧牲。單個mbuf的總長是128個字節,里面有20個字節是mbuf的首部,包含了這個mbuf個體的一些信息。其中包括:
- m_next 指向mbuf鏈中的下一個mbuf的指針,m_next把多個mbuf連在一起,形成一條mbuf鏈表。
- m_nextpkt 指向下一個mbuf鏈的指針,m_nextpkt把多個多個mbuf鏈表連在一起,形成一個mbuf鏈表的隊列。
- m_len 此mbuf中數據部分的大小
- m_data 指向此mbuf中數據
- m_type 此mbuf中數據的類型,可以為MT_DATA或MT_HEADER(比如存儲的是TCP報文段分組的首部)
- m_flags M_PKTHDR表示這個mbuf是此mubf鏈表中的第一個,即鏈表的頭,0表示此mbuf只包含數據,M_EXT表示此mbuf用到了外部的簇來存儲較大的數據。
mbuf頭部的代碼如下:
1 /* header at beginning of each mbuf: */ 2 struct m_hdr { 3 struct mbuf *mh_next; /* next buffer in chain */ 4 struct mbuf *mh_nextpkt; /* next chain in queue/record */ 5 int32_t mh_len; /* amount of data in this mbuf */ 6 caddr_t mh_data; /* location of data */ 7 short mh_type; /* type of data in this mbuf */ 8 short mh_flags; /* flags; see below */ 9 };
而mbuf結構的代碼如下:
1 struct mbuf { 2 struct m_hdr m_hdr; 3 union { 4 struct { 5 struct pkthdr MH_pkthdr; /* M_PKTHDR set */ 6 union { 7 struct m_ext MH_ext; /* M_EXT set */ 8 char MH_databuf[_MHLEN]; 9 } MH_dat; 10 } MH; 11 char M_databuf[_MLEN]; /* !M_PKTHDR, !M_EXT */ 12 } M_dat; 13 };
從mbuf的結構代碼中可以看出,在數據部分使用了union,包括了可選的mbuf分組首部,由m_flags來控制不同類型的mbuf,也分別具有額外的pkthdr首部或者m_ext首部。
參考資料: