TCP/IP中代码学习(1)

本来想等再从新看一遍书来整理下的,不过公司以后有个讨论会,先发上来,大家看到的提提意见呀!

开源是众多程序员们进步的一大阶梯,仅仅一个月来了解TCP/IP的实现,就越发感到自己的不足。对于整体协议的把握,任务的划分,内核与用户之间的转换,锁的设定都需要艺术的解决,甚至一个宏,一个联合都是自己以前万万想不到的。

再次从头开始阅读,带着敬意,走进大师的代码。

在BSD4.4版的TCP/IP实现,数据之间的传输的缓冲区命名为mbuf,这一结构需要完成的功能有

1. 各个层次的首部信息,并且要方便的添加。

2. 完成大容量内容的保存。传

3. 递插口信息

4. 标示分组首部等等。

同时,这一缓冲区的生成、删除、修改的层次不定,例如可以是以太网驱动调用m_devget来缓存一个帧,也可能是sendto请求缓存来将插口层将发送的内容保存。需要仔细的设计处理器的优先级。

首先看一下标准的结构:

每一个mbuf都是标准的128字节,这样对于不同用途、不同类型的mbuf都可以用统一的眼光来看待,而具体区别使用联合的结构,通过flags来解读特定位置的数据。

mbuf总共可以分成 个部分:

[1] 首部结构 m_hdr ,这是一个所有类型mbuf(由mh_flags标识) 都统一拥有的类型。

包括 指向下一个不相干的mbuf链的指针mh_nextpkt 指向属于同一分组的下一块缓存mh_next 自身数据长度 自身数据指针 mbuf的用途 mbuf的类型

[2] 分组首部结构 pkthdr ,当mbuf用于存储分组首部时,利用此结构找到特定位置存储的分组总长度与接受接口的ifnet结构

[3] 簇结构 - 簇的起始地址 一个未使用的指针 及簇的总大小

有了[2]和[3],就可以完成mbuf的主要四种类型——

纯数据内容:flags = 0  联合M_dat中的 M_databuf[MLEN]

短数据报的分组首部: M_PKTHDR 联合M_dat 中的 MH_pkthdr和联合MH_dat中的MH_databuf[MHLEN]

不含首部的大数据: M_EXT

含较多数据的分组首部: M_EXT / M_PKTHDR 联合M_dat 中的 MH_pkthdr和联合MH_dat中的MH_databuf[MHLEN]

同时对于宏定义的使用,这里有非常好的一个实例,由于把通用结构抽象出去作为一个公用的结构体,传统的使用就会变为m.m_hdr.mh_next

统一的,使用了简化技术:"我们会看到这种技术普遍应用于Net/3源代码中,只要是一个结构包含其他结构或联合这种情况"

#define m_pkthdr   M_dat.MH.MH_pkthdr

......

到了令我大开眼界的地方:

MGET是一个宏,用于分配一个缓存区,如果分配失败,则调用下面这段代码——调用协议的drain函数,可能会产生新的可供分配的空间,从而再次尝试分配缓存区。

struct mbuf *
m_retry(i,t)
int i,t;
{
struct mbuf *m;
m_reclaim();
#define m_retry(i, t) (struct mbuf *)0
MGET(m, i, t);
#undef m_retry
return (m);
}

在这里,再次使用了MGET宏来申请缓冲区。防止新的展开又再次调用m_retry。将m_retry这个函数定义为空指针,调用MGET,并在下一语句恢复。

原文地址:https://www.cnblogs.com/amaoxiaozhu/p/2167166.html