《TCP/IP详解 卷2:实现》 —2.4 mbuf结构
2.4 mbuf结构
图2-8所示的是mbuf结构的定义。
图2-8 mbuf结构
图2-8 (续)
结构mbuf是用一个m_hdr结构跟着一个联合来定义的。如注释所示,联合的内容依赖于标志M_PKTHDR和M_EXT。
93-103 这11个#define语句简化了对mbuf结构中的结构与联合的成员的访问。我们会看到这种技术普遍应用于Net/3源代码中,只要是一个结构包含其他结构或联合这种情况。
我们在前面说明了结构mbuf中前两个成员的作用:指针m_next把mbuf链接成一个mbuf链表,而指针m_nextpkt把mbuf链表链接成一个mbuf队列。
图1-8显示了每个mbuf的成员m_len与分组首部中的成员m_pkthdr.len的区别。后者是链表中所有mbuf的成员m_len的和。
图2-9所示的是成员m_flags的五个独立的值。
图2-9 m_flags的值
我们已经说明了标志M_EXT和M_PKTHDR。M_EOR在一个包含记录尾的mbuf中设置。Internet协议(例如TCP)从来不设置这个标志,因为TCP提供无记录边界的字节流服务。但是OSI与XNS运输层要用这个标志。在插口层我们会遇到这个标志,因为这一层是协议无关的,并且它要处理来自或发往所有运输层的数据。
当要往一个链路层广播地址或多播地址发送分组,或者要从一个链路层广播地址或多播地址接收分组时,在这个mubf中要设置标志M_BCAST和M_MCAST。这两个常量是协议层与接口层之间的标志(图1-3)。
对于最后一个标志M_COPYFLAGS,当一个mbuf包含一个分组首部的副本时,这个标志表明这些标志是复制的。
图2-10所示的常量MT_xxx用于成员m_type,指示存储在mbuf中的数据的类型。虽然我们总认为一个mbuf是用来存放要发送或接收的用户数据的,但mbuf可以存储各种不同的数据结构。回忆图1-6中的一个mbuf被用来存放一个插口地址结构,其中的目标地址用于系统调用sendto。它的m_type成员被设置为MT_SONAME。
不是图2-10中所有的mbuf类型值都用于Net/3。有些已不再使用(MT_HTABLE),还有一些不用于TCP/IP代码中,但用于内核的其他地方。例如,MT_OOBDATA用于OSI和XNS协议,但是TCP用不同方法来处理带外(out-of-band)数据(我们在29.7节说明)。当我们在本书的后面遇到其他mbuf类型时会说明它们的用法。
图2-10 成员m_type的值
本图的最后一列所示的M_xxx值与内核为不同类型mbuf分配的存储器片有关。这里有大约60个可能的M_xxx值指派给由内核函数malloc和宏MALLOC分配的不同类型的存储器空间。图2-6所示的是来源于命令netstat -m的mbuf分配统计信息,它包括每种MT_xxx类型的统计。命令vmstat -m显示了内核的存储分配统计,包括每个M_xxx类型的统计。
由于mbuf有固定的长度(128字节),因此对于mbuf的使用有一个限制—包含的数据不能超过108字节。Net/3用一个mbuf来存储一个TCP协议控制块(在第24章我们会讨论),这个mbuf的类型为MT_PCB。但是4.4BSD把这个结构的大小从108字节增加到140字节,并为这个结构使用一种不同的内核存储器分配类型。
仔细的读者会注意到图2-10中我们表明未使用MT_PCB类型的mbuf,而图2-6中显示这个类型的计数不为零。Unix域协议使用这种类型的mbuf,并且mbuf的统计功能用于所有协议,而不只是Internet协议,记住这一点很重要。
- 点赞
- 收藏
- 关注作者
评论(0)