网卡驱动在向内核注册网络设备时,可传入带有格式参数的网卡名,如eth%d,交由内核自动选择网卡名称。
struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs)
{
return alloc_netdev_mqs(sizeof_priv, "eth%d", ether_setup, txqs, rxqs);
}
在alloc_netdev调用之后,net_device结构体中的name成员为(eth%d)。之后的设备注册函数register_netdevice在注册过程中,使用函数dev_get_valid_name分配完整的设备名称。
int register_netdevice(struct net_device *dev)
{
ret = dev_get_valid_name(net, dev, dev->name);
}
内核最终调用__dev_alloc_name确定设备的名称。内核可支持的设备数量最大为8*PAGE_SIZE,即一个页面的大小的比特数量(通常为8*4K=32k个设备总是)。每一位代表一个设备。当前需要做的就是,在net命名空间中,遍历所有的设备名称,将其索引值在一个空白页面中的应用位置置位。遍历完成之后,只需要在页面中查找第一个未置位的位,作为新设备的索引值。将其替换name格式字符串中的%d,赋值于buf保存新的设备名称。
static int __dev_alloc_name(struct net *net, const char *name, char *buf)
{
const int max_netdevices = 8*PAGE_SIZE;
inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC);
for_each_netdev(net, d) {
if (!sscanf(d->name, name, &i))
continue;
set_bit(i, inuse);
}
i = find_first_zero_bit(inuse, max_netdevices);
snprintf(buf, IFNAMSIZ, name, i);
}
内核版本
Linux-4.15