注意到這麼龐大的結構中,有個成員叫: struct net_device *next,呵呵,很熟悉吧,就是用它來建立網絡設備的鏈表。
每一個網絡設備啟動的時候,都會調用register_netdev() (drivers/net/net_init.c)
跟蹤這個函數:
int register_netdev(struct net_device *dev)
{
int err;
rtnl_lock();
/*
* If the name is a format string the caller wants us to
* do a name allocation
*/
if (strchr(dev->name, '%'))
{
err = dev_alloc_name(dev, dev->name);
if (err < 0)
goto out;
}
/*
* Back compatibility hook. Kill this one in 2.5
*/
if (dev->name[0]==0 || dev->name[0]==' ')
{
err = dev_alloc_name(dev, "eth%d");
if (err < 0)
goto out;
}
err = register_netdevice(dev);
out:
rtnl_unlock();
return err;
}
跟蹤至: register_netdevice(struct net_device *dev) (net/core/dev.c)
int register_netdevice(struct net_device *dev)
{
struct hlist_head *head;
struct hlist_node *p;
int ret;
BUG_ON(dev_boot_phase);
ASSERT_RTNL();
/* When net_device's are persistent, this will be fatal. */
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
spin_lock_init(&dev->queue_lock);
spin_lock_init(&dev->xmit_lock);
dev->xmit_lock_owner = -1;
#ifdef CONFIG_NET_CLS_ACT
spin_lock_init(&dev->ingress_lock);
#endif
ret = alloc_divert_blk(dev);
if (ret)
goto out;
dev->iflink = -1;
/* Init, if this function is available */
//如果dev -> init 被賦值,那麼調用此函數
if (dev->init) {
ret = dev->init(dev);
if (ret) {
if (ret > 0)
ret = -EIO;
goto out_err;
}
}
//判斷name 是否合法
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
goto out_err;
}
//為此設備分配一個index
dev->ifindex = dev_new_index();
if (dev->iflink == -1)
dev->iflink = dev->ifindex;
/* Check for existence of name */
//所有網絡設備,以名字作為哈希主鍵存在dev_name_head中,該變量是一個哈希數組
//找到該名字對應的鏈表
//如果內核中已經含有此名字的網絡設備,出錯退出
head = dev_name_hash(dev->name);
hlist_for_each(p, head) {
struct net_device *d
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
goto out_err;
}
}
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & (NETIF_F_IP_CSUM |
NETIF_F_NO_CSUM |
NETIF_F_HW_CSUM))) {
printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
dev->name);
dev->features &= ~NETIF_F_SG;
}
/*
* nil rebuild_header routine,
* that should be never called and used as just bug trap.
*/
//為rebuild_header賦默認值
if (!dev->rebuild_header)
dev->rebuild_header = default_rebuild_header;
/*
* Default initial state at registry is that the
* device is present.
*/
set_bit(__LINK_STATE_PRESENT, &dev->state);
dev->next = NULL;
dev_init_scheduler(dev);
write_lock_bh(&dev_base_lock);
//初始化的時候,有struct net_device **dev_tail = &dev_base;
//這段代碼的意思實際就是:把dev加入dev_base為首結點隊鏈表的尾部
*dev_tail = dev;
dev_tail = &dev->next;
//把此結點加入到以名字為哈希主鍵的鏈表數組dev_name_head中
hlist_add_head(&dev->name_hlist, head);
//把此結點加到以序號為主鍵的鏈表數組dev_index_head中