mbuf在TCP/IP协议簇里非常重要,它是TCP/IP的核心数据结构。它的主要用途是保存在进程和网络接口间互相传递的用户数据,但也用于保存其它各种数据,如源地址和目标地址、套接字选项等。
按照mbuf的m_flags字段的不同,mbuf可分为四类如下:
m_flags=0:该mbuf只包含分组的用户数据(最大为108字节),记为mbuf1。
m_flags=M_PKTHDR:该mbuf包含分组的首部,以及不超过100字节的用户数据,记为mbuf2。
m_flags=M_EXT:该mbuf不包含分组的首部,但包含208~1024(或2048,看协议的实现)字节的用户数据,记为mbuf3。
m_flags=M_PKTHDR|M_EXT:该mbuf包含分组的首部,以及超过208~1024(或2048)字节的用户数据,记为mbuf4。
这里有一个疑问:只要有mbuf1和mbuf2,原则上就可以表示任意分组(分组的用户数据小于100字节只用mbuf2就够了;如果分组的用户数据大于100字节,就用一个mbuf2链接上若干个mbuf1,总能表示),为什么还需要mbuf3和mbuf4呢?是出于性能的考虑。mbuf作为TCP/IP的核心数据结构,对它操作的时间复杂度对协议的运行效率有重大影响。因为TCP发送的报文段从来不超过1024字节,连续访问1024字节的数组明显比访问一共1024字节的几个链表块,明显快得多。
mbuf不是一个链表结构,它是一个128字节的结构体。所有类型的mbuf都有以下6个字段,即mbuf的头部,共20字节:
m_next:本分组的下一个mbuf块的地址,4字节
m_nextpkt:下一个分组的首部的地址,4字节
m_len:本mbuf中有效数据的长度(不包括头部),4字节
m_data:本mbuf块有效数据的起始地址,4字节
m_type:本mbuf的数据类型,2字节
m_flags:区分mbuf块,2字节
对应的C源码如下:
struct m_hdr {
struct mbuf *mh_next;
struct mbuf *mh_nextpkt;
int mh_len;
char *mh_data;
short mh_type;
short mh_flags;
};