我是靠谱客的博主 开心老虎,最近开发中收集的这篇文章主要介绍Linux网络技术学习(六)—— 网络设备初始化(II),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

    • 初始化选项
    • 模块选项
    • 设备处理层初始化:net_dev_init
    • 用户空间辅助程序
    • kmod解析
    • 热插拔
    • 虚拟设备
    • 虚拟设备范例
    • 通过/proc文件系统调整


初始化选项

内核内建的组件以及模块加载的组件都能输入参数,使用户调整组件所实现的功能、重写默认值等

模块选项(module_param系列的宏)
使用module_param宏可以在文件系统中/sys文件夹下生成变量选项,通过这些文件在运行期间配置这些选项向内核提供这些配置选项。

引导期间内核选项(__setup系列的宏)
在引导加载程序引导期间可以提供这些定义选项。


模块选项

内核模块采用 宏的方式定义其参数。

// include/linux/moduleparam.h
#define module_param(name, type, perm)              
    module_param_named(name, name, type, perm)
    
module_param(rtw_tx_bw_mode, uint, 0644);

第一个输入参数是给用户使用的参数名称;第二参数类型(整形);第三个表示参数作为文件输出到/sys/时,分派给该文件的权限

root@linaro-alip:/sys/module/wlan/parameters# ls -l rtw_tx_bw_mode
-rw-r--r-- 1 root root 4096 Feb 14 18:58 rtw_tx_bw_mode

每个模块都在/sys/modules中分派一个目录。子目录/sys/module/对应模块/parameters中的每个文件就是该模块所输出的每个参数。组件程序员想让用户可以读取参数的值,至少必须给予读取权限。也可以提供写权限,允许用户可以修改参数的值。

/sys/中的文件和文件系统下的文件权限使用方法相同,使用拥有者权限对其修改也是可以的。


设备处理层初始化:net_dev_init

网络代码初始化的重要部分,包括流量控制和各个CPU入口队列,这个函数定义在<net/core/dev.c>

static int __init net_dev_init(void)
{
}

subsys_initcall(net_dev_init);

subsys_initcall宏确保任何NIC设备驱动程序自行注册前net_dev_init会先执行

net_dev_init的主要部分:
1、由两个网络软件中断(softirq)所使用的对应各个CPU的数据结构被初始化。

    open_softirq(NET_TX_SOFTIRQ, net_tx_action);
    open_softirq(NET_RX_SOFTIRQ, net_rx_action);

2、当内核被编译为支持/proc文件系统时,文件会通过dev_proc_init添加到/proc

    if (dev_proc_init())
        goto out;

3、协议处理例程向量ptype_base初始化,用于分离入口流量的多路合并传输。


用户空间辅助程序

有些情况下,内核调用用户空间应用程序以处理事件也是可以的。这又两个重要的辅助程序:
/sbin/modprobe
  当内核需要加载模块时就会被调用
/sbin/hotplug
  当内核侦测到一个新设备已经插入或拔出系统时会被调用。主要工作是根据设备标识符加载正确的设备驱动程序。

内核提供一个名为call_usrmodehelper的函数,以执行这类用户空间辅助程序。
此函数允许调用者通过arg[ ] 传递给一些自变量,并通过env[ ] 传递一些环境变量给应用程序。
第一个自变量arg[0]通知call_usrmodehelper要启用哪个用户空间辅助程序,而arg[1]可以用于通知辅助程序该使用什么配置脚本。

两个内核函数request_moudle和kobject_hotplug如何调用call_usrmodehelper?以调用/sbin/modprobe和/sbin/hotplug。


kmod解析

kmod是内核模块加载程序,允许内核组件请求加载一个模块。内核提供的请求加载模块的函数不止一个,这里介绍request_moudle。
此函数用要加载的模块名字初始化arg[1]。/sbin/modprobe使用配置文件/etc/modprobe.conf去做各式各样的事情,其中之一就是去了解从内核所接收的模块名字实际上是否为其他模块的别名。
在这里插入图片描述
当管理员使用ifconfig配置一张设备驱动程序尚未加载的网卡
如:设备eth0,内核向/sbin/modprobe送出一个请求,以加载名称为字符串“eth0”的模块。如果/eth0/prorobe.conf(没有这个文件就是在/etc/modprobe.d文件夹下面)包含“alias eth0 3c59x”字符,则/sbin/modprobe会尝试加载模块3c59x.ko

当管理员以IPROUTE2包的tc命令配置一个设备的流量控制时,可能会涉及不在内核内的队列规则或分类器。在这种情况下,内核将回向/sbin/modprobe发送一个请求,以加载相关模块。


热插拔

Linux内核引入热插拔是为了实现消费者即插即用功能。这个功能让内核去检测可热插拔设备的插入或删除,然后通知应用层程序,给足够细节,使其在必要时加载相关联的驱动程序,或者当驱动存在时应用相关联的配置。

热插拔实际上也可在引导期间用于非可热插拔设备。无论一个设备是热插在运行中的系统上,或者在引导期间已插在系统上,用户空间辅助程序都会收到这两种情况的通知信息。用户空间应用程序再决定需要执行什么动作。

Linux系统在引导期间执行一组脚本对接口设备做初始化,包括网口设备在内。这些设备的配置会在/etc/rc.d/下的每个执行等级下都有一个目录。

当你编译内核模块时,目标文件默认放在/lib/modules/kernel_version/目录下,而kernel_version为内核版本号(如:2.6.12)。在同一目录下,有两个文件:
modules.pcimap和modules.usbmap : 内核所支持设备的PCI ID和USB ID。还包含了相关联的内核模块引用(每个设备ID都有)

当用户空间辅助程序接收到一个可热插拔设备正在插入的通知信息时,就会使用这些文件找出正确的设备驱动程序。

module.xxxmap文件的填写数据来自设备驱动程序所提供的ID向量,Vortex驱动程序会对其pci_device_id实例做初始化。因为驱动程序是针对PCI设备编写的,所以该表的内容会加入到modules.pcimap

/sbin/hotplug
Hotplug默认的用户空间辅助程序/sbin/hotplug,该脚本是Hotplug套件的一部分。
套件可以通过默认目录/etc/hotplug/和/etc/hotplug.d/中的文件进行配置。

内核会调用kobject_hotplug会把arg[0]的初值设为/sbin/hotplug,把arg[1]设为要使用的代理程序:/sbin/hotplug是一个简单的脚本,把事件的处理委托给arg[1]指定的另一个脚本。

当一块NIC添加到系统或从系统删除时,kobject_hotplug会把arg[1]的初值设为net,使得/sbin/hotplug去执行net.agent代理程序。(net.agent并不代表一种媒体或总线类型)虽然net代理程序可用于配置设备,但其他代理程序可根据设备标识符而加载正确的模块。设备标识符是由内核通过INTERFACE环境变量传入的。


虚拟设备

虚拟设备是建立在一个或多个真是设备之上的抽象。虚拟设备和真实设备之间的关联可以是多对多。
在这里插入图片描述


虚拟设备范例

Linux允许你定义多种不同的虚拟设备
绑定(bonding)

  利用这个功能,虚拟设备可以绑定一组物理设备
802.1Q
  这是一种IEEE标准,VLAN的报头扩充802.3/Ethernet帧头。
桥接
  桥接接口就是网桥的虚拟代表
别名接口
  原本这项功能的主要目的是允许单一真实的Ethernet接口横跨几个虚拟接口(eth0:0,eth0:1等等),每个接口都有自己的IP配置。
现在,由于网络代码的改进,在同一个NIC上配置多个IP地址已经不需要定义一个新的虚拟接口。然而有些情况下(特别是路由),让同一个NIC具有不同的虚拟NIC会轻松点。
普通均衡器
  这是队列规则,用于流量控制。、
接收
  因为虚拟设备都是软件对象,不需要与系统上真实资源的交互,如注册IRQ处理例程或者分配I/O端口以及I/O内存。其流量是间接获取的,来自执行这些任务的物理设备。不同类型的虚拟设备在封包接收时各有不同的行为。
外部通知信息
  内核中发生其他内核组件 对特定事件发出通知信息,对虚拟设备而言,就如同真实设备一样,有其利益所在。因为虚拟设备的逻辑是实现在真实设备之上的。真实设备对此逻辑毫无所知,因此无法把这些通知信息传出去。


通过/proc文件系统调整

/proc中的一些文件会输出内部数据结构和配置参数的值,有助于记录设备驱动程序分配了哪些资源。
在/proc/net中,可以找到由net_dev_init通过dev_proc_init和dev_mcast_init所创建的文件。
在这里插入图片描述
dev
  对每个已注册至内核的网络设备而言,会显示一些有关接收和传输的统计数据。(已接收或已传输的字节数、封包数目等)
dev_mcast
  对每个已注册至内核的网络设备而言,会显示一些由IP多播所使用的参数值。
wireless
  对每个无线设备而言,会打印出来自dev->get_wireless_stats虚拟函数所返回的无线区块中的一些参数值。(只包含无线设备)
softnet_stat
  输出有关由网络代码所用的软件中断的统计数据。

最后

以上就是开心老虎为你收集整理的Linux网络技术学习(六)—— 网络设备初始化(II)的全部内容,希望文章能够帮你解决Linux网络技术学习(六)—— 网络设备初始化(II)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部