mbuf的主要用途是保存子进程和网络接口间互相传递的用户数据。但mbuf也用于保存其他各种数据:源于目的地址、插口
选项等等。
下面介绍我们要遇到的四种类型的mbuf,它们依据在成员m_flag中填写的不同标志M_PKTHDR和M_EXT而不同。
1.如果m_flags等于0,mbuf只包含数据,在mbuf中有108字节的数据空间(m_dat数组)。指针m_data指向这108字节缓
存中的某个位置。我们所示的m_data指向缓存的起始,但它能指向缓存中的任意位置。成员m_len指示了从m_data开始的
数据字节数。
2.第二类mbuf的m_flags值是M_PKHTR,它指示这是一个分组首部,描述一个分组数据的第一个mbuf。数据仍然保存在这个
mbuf中,但是由于分组首部占用了8字节,只有100字节的数据可存储在这个mbuf中(在m_pktdat数组中)。
成员m_pkthdr.len的值是这个分组的mbuf链表中所有数据的总长度:即所有通过m_next指针链接的mbuf的m_len值的和,输出
分组没有使用成员m_pkthdr.rcvif,但对于接收的分组,它包含一个指向接口ifnet结构的指针。
3.下一种mbuf不包含分组首部(没有设置K_PKTHDR),但包含超过208字节的数据,这是用到一个叫簇的外部缓存
(设置M_EXT)。在此mbuf中仍然为分组首部结构分配了空间,但没有用。Net/3分配一个大小为1024或2048字节的簇,而不是
使用多个mbuf来保存数据。这个mbuf中,指针m_data指向这个簇中的某个位置。
4.最后一类mbuf包含一个分组首部,并包含超过208字节的数据,同时设置了标识M_PKTHDR和M_EXT。
有几点需要说明:
1.mbuf结构的大小总是128个字节,这意味着上图mbuf在m_ext后面的未用空间为88字节。
2.既然有些协议(如UDP)允许零长记录,当然就可以有m_len为0的数据缓存。
3.在每个mbuf中的成员m_data指向相应缓存的开始。这个指正能指向相应缓存的任意位置,不一定是起始。
4.带有簇的mbuf总是包含缓存的起始地址(m_ext.ext_buf)和它的大小(m_ext.ext_size)。成员m_data和m_ext.ext_buf值
是不同的,除非m_data也指向缓存的第一个字节。结构m_ext的第三个成员ext_free,Net/3当前未使用。
5.指针m_next把mbuf链接在一起,把一个分组形成一条mbuf链表。
6.指针m_nextpkt把多个多个分组链接成一个mbuf链表队列。在队列中的每个分组可以使一个单独的mbuf,也可以是一个
mbuf链表。每个分组的第一个mbuf包含一个分组首部,如果多个mbuf定义一个分组,只有第一个mbuf的成员m_nextpkt被
使用,其他的都是空指针。
下图所示是一个队列中两个分组的例子。
mbuf的定义如下:
有很多操作mbuf的函数,比如我们要发送一个分组,则需要创建新的mbuf,并将分组数据复制到mbuf中,使用完分组后,需要
释放掉mbuf。
宏函数如下:
普通函数如下: