灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2290回复:0

Linux网络协议栈之设备初始化

楼主#
更多 发布于:2012-08-27 15:01

Linux网络协议栈的内核初始化工作大致分为设备链路层(e100_module_init、net_dev_init)、网络层(inet_init)、传输层(proto_init)、应用层(sock_init)初始化。由于物理层为具体的网络设备,所以内核对网络协议栈的实现以及网卡驱动实现等没有物理层(L1),驱动以及设备的初始化函数都应该化为L2层。前面介绍了e100系列网卡驱动的实现,下面我们看看内核初始化的时候对设备初始化的另一个函数net_dev_init。
/*设备处理层的初始化函数*/
static int __init net_dev_init(void)
{  
         int i, rc = -ENOMEM;
         /*没有被初始化*/
         BUG_ON(!dev_boot_phase);
         /*该函数在/proc目录下创建三个文件,主要用于读取网络相关统计数据
         正如我们看到的,/proc下的文件基本都为只读的,这里提供的三个文件
         都没有写操作*/
         if (dev_proc_init())
                   goto out;
         /*在/sysfs设备文件系统的class中注册net节点*/
         if (netdev_sysfs_init())
                   goto out;
        
         /*初始化网络处理函数链表和散列表,这些函数是用来处理接收到的不同
         协议族报文*/
         INIT_LIST_HEAD(;ptype_all);
         for (i = 0; i < 16; i++)
                   INIT_LIST_HEAD(;ptype_base);
         /*下面为初始化存放网络设备的散列表*/
         /*散列表关键字由设备名称计算获得*/
         for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)
                   INIT_HLIST_HEAD(;dev_name_head);
         /*散列表关键字由设备接口索引计算获得*/
         for (i = 0; i < ARRAY_SIZE(dev_index_head); i++)
                   INIT_HLIST_HEAD(;dev_index_head);
         /*
          *     Initialise the packet receive queues.
          */
         /*初始化与cpu相关的数据接收队列*/
         for_each_possible_cpu(i) {
                   struct softnet_data *queue;
                   queue = ;per_cpu(softnet_data, i);
                   skb_queue_head_init(;queue->input_pkt_queue);
                   queue->completion_queue = NULL;
                   INIT_LIST_HEAD(;queue->poll_list);
                   set_bit(__LINK_STATE_START, ;queue->backlog_dev.state);
                   queue->backlog_dev.weight = weight_p;
                   queue->backlog_dev.poll = process_backlog;
                   atomic_set(;queue->backlog_dev.refcnt, 1);
         }
         /*注册网络DMA客户端*/
         netdev_dma_register();
         /*标志已经初始化*/
         dev_boot_phase = 0;
         /*注册两个软件中断用于数据接收和发送*/
         open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
         open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
         /*在通知链表中注册一个回调函数,用于相应CPU热插拔事件
         由回调函数可以看出,一旦接到通知,CPU输入队列中的包逐一
         交由netif_rx()处理*/  
         hotcpu_notifier(dev_cpu_callback, 0);
         /*初始化目的路由缓存,通知链的方式*/
         dst_init();
         /*初始化网络链路层的组播模块,在/proc/net下创建文件dev_mcast
         用来存放内核中网络设备与IP组播相关的参数*/
         dev_mcast_init();
         rc = 0;
out:
         return rc;
}
Net_dev_init函数在驱动程序之前调用,用于初始化一些必要的信息,包括两种设备队列、数据输入输出队列以及注册两个用于接收和发送数据的软中断等。另外,上面各种初始化函数的层次划分可能不正确,只是便于理解。

喜欢0 评分0
游客

返回顶部