//在socket文件系统注册之后,设备驱动程序注册之前被调用 //start_kernel->rest_init->kernel_thread->init->do_basic_setup->do_initcalls->net_dev_init 2.1 static int __init net_dev_init(void) { ... //proc文件系统中相关项的初始化 if (dev_proc_init()) goto out; //注册网络设备类 if (netdev_sysfs_init()) goto out; //初始化ETH_P_ALL的链表 INIT_LIST_HEAD(&ptype_all); //初始化l3协议的hash表 //通过dev_add_pack和dev_remove_pack添加l3协议 //链表元素为struct packet_type for (i = 0; i < 16; i++) INIT_LIST_HEAD(&ptype_base[i]); //初始化与设备相关的两个hash表 //其中一个hash设备名 for (i = 0; i < ARRAY_SIZE(dev_name_head); i++) INIT_HLIST_HEAD(&dev_name_head[i]); //另一个hash设备编号 for (i = 0; i < ARRAY_SIZE(dev_index_head); i++) INIT_HLIST_HEAD(&dev_index_head[i]); //初始化per-cpu的接收队列 for (i = 0; i < NR_CPUS; i++) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); //不适用napi的设备的接收到的流量将会挂载到此queue上 skb_queue_head_init(&queue->input_pkt_queue); //与拥塞管理算法相关的字段 //表示cpu当前接收队列是否被关闭,当input_pkt_queue满时,throttle=1, //标示此cpu的接收功能被关闭,当第一个帧排入空队列时,throttle会被netif_rx消除(注:netif_rx由非napi设备调用) queue->throttle = 0; //cng_level, avg_blog在get_sample_stats中被更新 //get_sample_states由netif_rx调用 queue->cng_level = 0;//拥塞等级 queue->avg_blog = 10; //平均值 //缓冲区list,其中为完成传输的skb,等待被释放 queue->completion_queue = NULL; //此list上的设备都带有输入帧接收轮询,中断功能被关闭 INIT_LIST_HEAD(&queue->poll_list); //不使用napi的设备,linux默认提供一个积压设备,完成轮询 //__LINK_STATE_START表示设备已开启 set_bit(__LINK_STATE_START, &queue->backlog_dev.state); //设置积压设备的权重,weight_p通过proc文件系统修改 queue->backlog_dev.weight = weight_p; //积压设备的轮询函数 queue->backlog_dev.poll = process_backlog; atomic_set(&queue->backlog_dev.refcnt, 1); } //注册网络传输和接收的软中断 open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); //注册dst通知链,通知dst_entry子系统有关net_device unregister、ifdown的event dst_init(); //多播的初始化 dev_mcast_init(); rc = 0; out: return rc; } //subsys_initcall的优先级低于core_initcall subsys_initcall(net_dev_init);