歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux管理 >> Linux網絡

Linux網絡協議棧之網絡設備管理(續)

注意到這麼龐大的結構中,有個成員叫: 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中

Copyright © Linux教程網 All Rights Reserved