📄 -
字号:
any problems, send mails to sindybear@163.com
相关文件
/drivers/block/genhd.c
***********************主要的数据结构*************************************
各种网络协议的哈希表,系统中使用的各种协议都填写到这个表中的相应位置。
用户使用哈希值访问这个表,得到这种协议的处理函数。继而得到处理。
用户使用函数dev_add_pack(struct packet_type *pt)来将各种协议的处理函数挂接到系统中,
这样,所有的linux系统可以处理的协议类型都在这个hash表中可以按照索引找到,或者在
ptype_all中找到。而每一个协议类型都有一个packet_type结构进行对应,这个结构中就有相应协议的
处理函数。
static struct packet_type *ptype_base[16];
static struct packet_type *ptype_all = NULL;
**************************************************************************
(1)__initcall(device_init); //系统启动的时候调用这个几乎所有的设备的初始化函数
(2)int __init device_init(void)
……
net_dev_init(); //进行网络初始化设置
……
(3)int __init net_dev_init(void)
……
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); //设置接受和发送的软中断的处理函数
open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
……
(4)static void net_rx_action(struct softirq_action *h) //这个函数就是接受IP包的处理函数
struct softnet_data *queue = &softnet_data[this_cpu]; //先得到Ip包队列
……
for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next){ //寻找适合的协议类型
if (ptype->type == type ) { //如果找到的话
pt_prev->func(skb,skb->dev,pt_prev); //调用这个协议的处理函数
} //例如,对于tcp/ip就是下面的ip_rcv函数
(5)void dev_add_pack(struct packet_type *pt)
……
ptype_base[hash] = pt; //注册不同的网络协议的处理函数
……
**************************TCP/IP的处理过程********************************
我们以TCP/IP为例来了解一下注册和IP包的处理过程
(1)module_init(inet_init); //这就是TCP/IP协议的安装点
(2)static int __init inet_init(void)
……
ip_init(); //建立协议栈
……
(3)void __init ip_init(void)
dev_add_pack(&ip_packet_type); //将自己的协议处理函数挂接在系统队列中
static struct packet_type ip_packet_type = //TCP/IP的协议处理函数所处的结构
{
__constant_htons(ETH_P_IP),
NULL,
ip_rcv, //IP包接受处理函数
(void*)1,
NULL,
};
(4)int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
//实际的TCP/IP的IP包接受处理函数,他被net_rx_action调用
**************************************************************************
************************ip包的进入和处理**********************************
当ip数据包进入到linux系统中以后,网卡接收到这个数据包以后,经过一些简单的校验等处理以后,
如果ip的数据缓冲区满了,就丢弃这个数据包,否则就挂接在相应的cpu的处理队列上(对于多cpu的系统来说)
然后就调用__cpu_raise_softirq(),前面的操作相当于上半部,然后调用这个函数以后,就将相应的软中断
机制的相应位置位,这以后就是bottom_half的处理了。
很明显,从上面的分析来看,在系统启动的时候,就是用open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL)
将net_rx_action注册为bottom_half的处理函数,这样,当下层的网卡使用__cpu_raise_softirq()以后,
不久就会调用net_rx_action,这个函数在经过选择,主要是选择相应的协议栈来进行处理,例如,
如果选择了tcp/ip协议,那么就会进一步调用ip_rcv函数,接下来的事情就是它的了
**************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -