用前端框架做自适应网站杭州住房和城乡建设部网站
news/
2025/9/27 0:32:36/
文章来源:
用前端框架做自适应网站,杭州住房和城乡建设部网站,wordpress不能更新,wordpress 文章内容页NIC注册和注销的通用架构Linux系统中NIC网络设备驱动程序利用网络代码进行注册和注销有其通用的架构#xff0c;这里以PCI Ethernet NIC为例#xff0c;其他设备类型只是所以函数名称和调用方式不同#xff0c;主要依据于设备总线提供的接口。其中(a)为设备注册的大致流程图…NIC注册和注销的通用架构Linux系统中NIC网络设备驱动程序利用网络代码进行注册和注销有其通用的架构这里以PCI Ethernet NIC为例其他设备类型只是所以函数名称和调用方式不同主要依据于设备总线提供的接口。其中(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 isnt 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_devices are persistent, this will be fatal. */BUG_ON(dev-reg_state ! NETREG_UNINITIALIZED); //alloc_netdev时不需要设置这个成员因为其为0BUG_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/918944.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!