linux dev alloc name,深入理解Linux网络技术内幕-设备注册和初始化(二)

NIC注册和注销的通用架构

Linux系统中NIC网络设备驱动程序利用网络代码进行注册和注销有其通用的架构,这里以PCI Ethernet NIC为例,其他设备类型只是所以函数名称和调用方式不同,主要依据于设备总线提供的接口。

6655815e36072d815b9909839e95f955.png

其中(a)为设备注册的大致流程图,而(b)为设备注销的流程图。

在PCI Ethernet NIC设备驱动程序的探测函数(热插拔设备)或模块初始化函数中,首先要为设备分配一个net_device数据结构,并对其中的成员进行必要的初始化,对其中与设备类型密切相关的特殊成员利用驱动程序自己实现的setup函数进行初始化;Ethernet NIC设备驱动程序还需要调用netdev_boot_setup_check检查是否在系统启动参数中对网络设备进行了设置;然后调用register_netdev完成设备的注册。

在分配net_device数据结构时,驱动程序一般不直接调用alloc_netdev函数,而是调用为其类型封装后的函数,如Ethernet NIC设备直接调用alloc_etherdev函数,使用更加方便简单。

而Ethernet NIC设备的注销则是相反的过程,首先调用unregister_netdev在系统中注销设备,然后将分配的net_device数据结构释放。

在释放net_device数据结构时,设备也可能不直接调用free_netdev函数中,而是调用net_device数据结构中的成员函数:

/* Called from unregister, can be used to call free_netdev */

void (*destructor)(struct net_device *dev);

虚拟设备驱动程序一般采用这种方式,实现自己的destructor函数来释放net_device数据结构。

网络设备注册过程

网络设备在系统中注册后,内核在处理数据包时才能调用设备接口实现的处理函数。网络设备的注册是通过register_netdev函数完成的:

/**

*    register_netdev    - register a network device

*    @dev: device to register

*

*    Take a completed network device structure and add it to the kernel

*    interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier

*    chain. 0 is returned on success. A negative errno code is returned

*    on a failure to set up the device, or if the name is a duplicate.

*

*    This is a wrapper around register_netdevice that takes the rtnl semaphore

*    and expands the device name if you passed a format string to

*    alloc_netdev.

*/

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;

}

err = register_netdevice(dev);

out:

rtnl_unlock();

return err;

}

EXPORT_SYMBOL(register_netdev);

其中rtnl_lock是内核保护运行时的net_device数据结构的互斥手段,一般在修改net_device中flag字段,表示有事件发生需要改变设备的状态;或者用户通过ifconfig、route等命令修改接口的配置时,通过ioctl和netlink接口告诉内核操作设备的net_device结构,都需要调用这个锁来进行互斥。

dev_alloc_name(dev, dev->name)函数会在系统中找到这种类型的网络设备中第一个没有使用的序列号来替换设备名称中的%d,生成如eth2的设备名称。

int dev_alloc_name(struct net_device *dev, const char *name)

{

char buf[IFNAMSIZ];

struct net *net;

int ret;

BUG_ON(!dev_net(dev));

net = dev_net(dev);

ret = __dev_alloc_name(net, name, buf);

if (ret >= 0)

strlcpy(dev->name, buf, IFNAMSIZ); //将返回的设备名称复制到net_device的name字段

return ret;

}

static int __dev_alloc_name(struct net *net, const char *name, char *buf)

{

int i = 0;

const char *p;

const int max_netdevices = 8*PAGE_SIZE;

unsigned long *inuse;

struct net_device *d;

/*检查设备名称中是否有%d,或其他不合法字符*/

p = strnchr(name, IFNAMSIZ-1, '%');

if (p) {

if (p[1] != 'd' || strchr(p + 2, '%'))

return -EINVAL;

/*分配一个物理页面作为位图,来对系统中该类型设备已用序列号进行标记*/

inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC);

if (!inuse)

return -ENOMEM;

/*变量网络命名空间中的所有设备,即net_device结构*/

for_each_netdev(net, d) {

if (!sscanf(d->name, name, &i)) //获取同类型网络设备的其序列号,这里极为巧妙

continue;

if (i < 0 || i >= max_netdevices) //判断序列号的范围

continue;

snprintf(buf, IFNAMSIZ, name, i);

if (!strncmp(buf, d->name, IFNAMSIZ)) /*验证解析的序列号是否正确*/

set_bit(i, inuse); //在位图中将该位标记

}

i = find_first_zero_bit(inuse, max_netdevices); //找到第一个为0的序列号

free_page((unsigned long) inuse);

}

if (buf != name)

snprintf(buf, IFNAMSIZ, name, i); //根据找到的序列号,输出完整的设备名

if (!__dev_get_by_name(net, buf)) //在name_list链表中查找是否有同名的设备

return i;

/* It is possible to run out of possible slots

* when the name is long and there isn't enough space left

* for the digits, or if all bits are used.

*/

return -ENFILE;

}

在这里就为设备完成了完整设备名的组合,内核在这里位图的使用非常巧妙,以后可以在处理位图时,可以直接使用内核实现的set_bit和find_first_zero_bit、clear_bit等函数。

register_netdevice才是网络设备注册的最重要步骤:

int register_netdevice(struct net_device *dev)

{

int ret;

struct net *net = dev_net(dev);  //设备的网络空间

BUG_ON(dev_boot_phase);

ASSERT_RTNL();

might_sleep();

/* When net_device's are persistent, this will be fatal. */

BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); //alloc_netdev时不需要设置这个成员,因为其为0

BUG_ON(!net);

/*初始化net_device中的一些成员锁*/

spin_lock_init(&dev->addr_list_lock);

netdev_set_addr_lockdep_class(dev);

dev->iflink = -1;

/* Init, if this function is available */

if (dev->netdev_ops->ndo_init) { //调用设备驱动程序操作中实现的初始化函数

ret = dev->netdev_ops->ndo_init(dev);

if (ret) {

if (ret > 0)

ret = -EIO;

goto out;

}

}

ret = dev_get_valid_name(dev, dev->name, 0); //检查设备名称的有效性

if (ret)

goto err_uninit;

dev->ifindex = dev_new_index(net); //为设备分配一个唯一的索引号

if (dev->iflink == -1)

dev->iflink = dev->ifindex;

/* Transfer changeable features to wanted_features and enable

* software offloads (GSO and GRO).

*/

/*设置设备的一些特性*/

dev->hw_features |= NETIF_F_SOFT_FEATURES;

dev->features |= NETIF_F_SOFT_FEATURES;

dev->wanted_features = dev->features & dev->hw_features;

/* Enable GRO and NETIF_F_HIGHDMA for vlans by default,

* vlan_dev_init() will do the dev->features check, so these features

* are enabled only if supported by underlying device.

*/

dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA);

ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); //调用通知链,发出事件通知

ret = notifier_to_errno(ret);

if (ret)

goto err_uninit;

ret = netdev_register_kobject(dev); //设备注册的核心函数,主要是调用device_add函数,将设备添加到内核的设备管理器中

if (ret)

goto err_uninit;

dev->reg_state = NETREG_REGISTERED;  //设置net_device的状态

netdev_update_features(dev);

/*

*    Default initial state at registry is that the

*    device is present.

*/

set_bit(__LINK_STATE_PRESENT, &dev->state);

dev_init_scheduler(dev); //在这里会设置设备的看门狗定时器

dev_hold(dev); //增加设备的引用计数

list_netdevice(dev);  //将设备加入系统的indexlist、namelist和devlist中

/* Notify protocols, that a new device appeared. */

ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); //通过通知链发出设备注册通知

ret = notifier_to_errno(ret);

if (ret) {

rollback_registered(dev);

dev->reg_state = NETREG_UNREGISTERED;

}

/*

*    Prevent userspace races by waiting until the network

*    device is fully setup before sending notifications.

*/

if (!dev->rtnl_link_ops ||

dev->rtnl_link_state == RTNL_LINK_INITIALIZED)

rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);

out:

return ret;

err_uninit:

if (dev->netdev_ops->ndo_uninit)

dev->netdev_ops->ndo_uninit(dev);

goto out;

}

EXPORT_SYMBOL(register_netdevice);

由上可知注册的主要过程是netdev_register_kobject函数中的device_add过程,和list_netdevice(dev)将设备加入到系统的几个hash链表中,便于系统处理数据包时查找对应的设备。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/560606.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外贸常用术语_外贸中常用的会计术语及付款方式术语 | 会计英语

点击上面“财经英语”关注公众号&#xff01;点击下面小程序加入: 学习圈财经英语 学习圈 预付现金 Cash advance 凭提货单支付现金 Cash against Bill of Lading (B/L) 凭单据付现款||凭装货单付现款 Cash against Documents 现金结存||现金差额 Cash balance 现收现付制||现金…

python 多维list 排序_一行代码的优雅| Python列表生成式

欢迎回来&#xff0c;上一周我们整理了基础课中三大结构有关内容的具体应用及案例。可以通过以下几篇推文进行回溯&#xff1a;Python语言基础50课我的Python - 100天笔记 |D1-D7我的Python - 100天笔记 |D8-D14列表是Python中非常常见的数据结构&#xff0c;在基础课中也占了不…

verilog 生成块_如何高效的编写Verilog——终极版

为了高效的编写Verilog&#xff0c;通常有些编辑器插件可以自动生成代码&#xff0c;比如自动端口定义&#xff0c;自动连线&#xff0c;自动实例化等等。公司的环境有很好用的自动化插件&#xff0c;想给自己的电脑也整个怎么做。比如Emacs中有个插件叫verilog-mode。但是博主…

剩余 大小 查看内存_JVM的内存分配策略以及进入分代的条件

JVM的参数和知识点太多啦&#xff0c;记录下来&#xff0c;供自己随时回顾。java对象什么时候进入年轻代&#xff08;新生代&#xff09;&#xff1f;java对象什么时候进入老年代&#xff1f;对象优先在Eden分配大对象直接进入老年代空间分配担保机制java对象什么时候进入年轻代…

Arduino的串口结束符及串口缓冲区

文章目录1.深入理解缓冲区和Serial.available()&#xff1a;2.深入理解串口结束符3.验证结论&#xff1a;1.深入理解缓冲区和Serial.available()&#xff1a; 运行下面的代码&#xff0c;我发现如果不在串口输入任何数字&#xff0c;就会一直显示“no”&#xff0c;输入一个数…

android 圆角边框边框渐变,支持边框、圆角、渐变色、透明度的GradientButton

最近在项目中发现好多Button背景颜色相同&#xff0c;但圆角大小不等的Button&#xff0c;这样就得写一大堆的shape或者selector&#xff0c;不便于管理及后期维护&#xff0c;于是乎变想能不能写一个支持边框、圆角、渐变色、透明度的万用Button呢。为了能够兼容button自带的属…

鸿蒙ide如何运行,深入浅析华为鸿蒙IDE安装与Hello World

一、系统安装1. 到官网下载HUAWEI DevEco Studio2. 安装二、创建项目创建项目目前还没有手机选项&#xff0c;所以我先选择一个电视&#xff1a;IDE的环境看起来和idea差不多&#xff0c;应该比较容易上手。从“关于”里也可以看到&#xff0c;确实是基于IDEA开源版本开发的。我…

中快捷搜索_同事用1分钟,我用半小时,原来是因为这8个Word快捷键,秒杀一切办公技巧...

同事用1分钟&#xff0c;我用半小时&#xff0c;这8个Word快捷键&#xff0c;秒杀一切办公技巧​mp.weixin.qq.com文&#xff5c;王羽卒今天给小伙伴们分享几个实用又有效的快捷键&#xff0c;帮助快速完成工作&#xff0c;同事用了半小时&#xff0c;你1分钟就能解决哟&#x…

荣耀x10max能不能升级为鸿蒙,荣耀终于放出大招!4部荣耀旗舰可升级鸿蒙,网友:终于等到了...

4月24~26日&#xff0c;华为将召开开发者大会&#xff0c;届时手机使用的鸿蒙系统将正式上线&#xff0c;华为和部分荣耀手机将会首先支持。其实&#xff0c;早在2月22日的华为Mate X2的发布会上&#xff0c;余承东就说过4月发布鸿蒙OS。华为并不想推出鸿蒙系统&#xff0c;如果…

android 7.0新增控件,自定义Android控件,封装Arcgis for Android测距测面积工具控件

控件的功能包括&#xff0c;测距、测面积、撤销、恢复、清除、完成六个功能。测距&#xff1a;在地图上绘制线段进行长度测量测面积&#xff1a;在地图上绘制一个面&#xff0c;进行面积测量撤销&#xff1a;撤销到上一步绘制&#xff0c;只能撤销未完成的测量恢复&#xff1a;…

多媒体分析与理解_如何设计一个出色的数字多媒体展厅?

展厅设计方案是了解每个多媒体设备的应用方法&#xff0c;那么如何让设备跟展厅结合一起&#xff0c;展示出我们想要的科技效果&#xff0c;核心就是用户体验度。今天华南数字科技的小编就为您介绍下数字多媒体展厅对用户体验方面的几个重点要素。1、细节展示不论多前卫的多媒体…

gradient设置上下渐变_图解CSS: CSS渐变

CSS的渐变主要分布在 conic-gradient()和repeating-conic-gradient()两个属性。在CSS中&#xff0c;CSS的渐变相当于图像&#xff0c;我们可以使用线性渐变(linear-gradient()和repeating-linear-gradient())、径向渐变(radial-gradient()和repeating-radial-gradient())和锥形…

2021泗阳致远中学高考成绩查询,2021高考成绩什么时候发布?可通过哪些途径查询?...

3、安徽省高考成绩预计将于6月23日公布各批次录取分数线和高考成绩&#xff0c;考生可通过安徽省教育招生考试院自行查分&#xff1b;4、湖南高考成绩将于6月25日左右公布&#xff0c;本科不再分一二三批&#xff0c;考生可通过湖南教育政务网、湖南省普通高校招生考试考生综合…

mysql数据库的字符集_mysql数据库中字符集乱码问题原因及解决

前言有的时候我们在查看数据库数据时&#xff0c;会看到乱码。实际上&#xff0c;无论何种数据库只要出现乱码问题&#xff0c;这大多是由于数据库字符集设定的问题。下面我们就介绍一下&#xff0c;数据库的字符集的设定及乱码问题的解决。mysql数据库的字符集直白的说&#x…

1主5从mysql数据库_MySQL主从复制虽好,能完美解决数据库单点问题吗?

一、单个数据库服务器的缺点数据库服务器存在单点问题&#xff1b;数据库服务器资源无法满足增长的读写请求&#xff1b;高峰时数据库连接数经常超过上限。二、如何解决单点问题增加额外的数据库服务器&#xff0c;组建数据库集群&#xff1b;同一集群中的数据库服务器需要具有…

惠普z6计算机进不去桌面,HP Z6 桌面工作站 | HP® HK 惠普香港

Intel、Thunderbolt 及 Xeon 均為 Intel Corporation 於美國及/或其他國家或地區的商標。Microsoft 及 Windows 為 Microsoft Corporation 於美國及/或其他國家或地區的註冊商標或商標。NVIDIA 是 NVIDIA Corporation 在美國及其他國家或地區的商標及/或註冊商標。USB Type-C™…

mysql定义条件和处理_mysql sql存储过程条件定义与处理

一、条件定义DECLARE condition_name CONDITION FOR condition_valecondition_value:sqlstate[value] sqldata_value |mysql教程_error_code二、条件处理DECLARE htype HANDLER FOR cond_value[...] sp_statementhandtype_value:sqlstate [value] saltate_value|contentname|sq…

长沙医学院学位计算机考试内容,湖南长沙医学院2017年9月计算机等级考试报名时间...

长沙医学院2017年下半年第49次全国计算机等级考试(以下简称NCRE)将于2017年9月23至25日举行。为做好本次考试报名及相关考务工作&#xff0c;现将有关事项通知如下&#xff1a;一、报名时间&#xff1a;2016年6月7日—2016年6月18日&#xff0c;逾期不接受任何理由的补报名。二…

mysql dnslog_dnslog小技巧

一、dnslog利用场景主要针对无回显的情况。Sql-BlindRCESSRFRFI(Remote File Inclusion)二、原理将dnslog平台中的特有字段payload带入目标发起dns请求&#xff0c;通过dns解析将请求后的关键信息组合成新的三级域名带出&#xff0c;在ns服务器的dns日志中显示出来。三、案例展…

2019哈佛计算机专业录取,2019哈佛大学早申请录取数据公布 录取率再降1个点仅为13.4%...

出结果了&#xff0c;出结果了&#xff0c;作为美国在全球范围内最负盛名的哈佛大学&#xff0c;与近日公布2019美国本科申请提前录取的相关数据。今年哈佛大学本科学院向6,968位在2023届提前录取轮次申请人中的935位发出了录取通知&#xff0c;申请录取率约为13.4%&#xff0c…