深入理解Linux网络技术内幕学习笔记第五章:网络设备初始化

第五章:网络设备初始化
系统初始化概论
设备驱动程序可以作为模块加载至内核,也可以作为内核的静态组件。此外设备可以在引导期间就存在,也可以在运行期间存在,后者称为可热插拔设备。
内核引导时,会执行start_kernel,对一些子系统初始化,start_kernel终止前会调用init内核线程负责初始化的后续工作。本章涉及的初始化多数都在do_basic_setup内发生的。
在各种初始化中主要有三点:
    引导期间选项:调用两次parse_args来处理引导加载程序(boot loader 如grub)在引导期间传给内核的配置参数。
    中断和定时器:本章只说明设备驱动程序如何把处理函数注册给IRQ,以及中断处理函数在内存是如何组织的。
    初始化函数:内核子系统及内建的设备驱动程序由do_initcalls初始化。
run_init_process确定在系统上运行的第一个进程,也就是所有其他进程的父进程,其pid为1,通常是init进程。但是可以提供init = 引导期间选项指定一个不同的程序。
设备注册和初始化
设备注册和初始化一部分由内核负责,其他由设备驱动程序负责。设备初始化有以下几个阶段:
    硬件初始化:由设备驱动程序和通用总线层(如PCI,USB)合作完成。驱动程序为设备配置IRQ和I/O地址。虚拟设备不需要分配一个IRQ。/proc/interrupts可观察当前分配状态。I/O端口的分配和释放调用reuqest_region和release_region来实现。
    软件初始化:在设备能够使用之前,依赖于所开启和配置的网络协议为何而定,用于需要提供以下参数如ip地址等。
    功能初始化:Linux内核有很多网络选项,设备初始化引导顺序负责这些选项。
在net_device结构中保函一组函数指针,内核可以它们与设备驱动及特殊内核功能交互。这些函数指针的初始化取决于设备类型,厂商等。
通过中断,NIC(网卡)能够告诉驱动程序下面几种不同的事:
    接收一帧。
    传输失败:驱动程序不会通知网络层传输失败了,网络层会通过定时器到期,ACK等方式获知。
    DMA传输完成:当要传输的帧加载到NIC的内存准备传输时,驱动程序会将持有该帧的缓冲区释放掉。
    设备有足够的内存处理新传输:当出口队列空间不足以保存一个最大尺寸的帧时,驱动程序会暂时停止出口队列。
中断:
设IRQ处理例程的映射存储在一张表中。用于存储此映射的数据结构是irqaction,其实就是用来描述中断处理例程的:
struct irqaction{
    void (*handler)(int irq,void *dev_id,struct pt_regs *regs);//设备驱动程序提供的函数,集中断处理函数
    /*该处理函数的参数:
    int irq;//中断编号,大多数时候有设备标识符就够了
    int *dev_id;//设备标识符,同一个驱动程序可能同时负责不同设备,所以需要设备ID
    struct pt_regs *regs;//保存被中断终止的进程的寄存器数据
    */
    unsigned long flags://一组标识。可能的取值在include/asm-XXX/signal.h,以x86为例:
    /*SA_SHIRQ:设备驱动可以处理共享的IRQ
      SA_INTERRUPT:当置位时,处理例程争被运行,且关闭了中断*/
    void *dev_id; //与设备相关联的net_device数据结构指针。因为除了NIC,还有其他设备,所以声明为void
    struct irqaction *next;//所有共享同一个IRQ编号的会用此指针连接成一个链表
    const char *name;//设备名称。可以在/proc/interrupts查看
};
初始化选项:
模块选项(module_param系列的宏) :
    当加载模块时可以提供这些定义选项。若组件内建在内核则不能在引导期间提供这些值。另外,可以通过/sys文件系统在运行期间配置这些选项。module_param有三个参数,分别是给用户使用的参数名称,参数类型,作为文件输出到/sys的权限。
    引导期间内核选项(__setup系列的宏):在引导加载程序引导期间可以提供这些定义选项。主要由内核内建的的组件使用。
设备处理层初始化:net_dev_init
模块网络代码初始化的重要部分,包括流量控制和各个CPU的入口队列,在引导期间又定义在net/core/dev.c中的net_dev_init完成:
static int _ _ init net_dev_init(void)
{
    ...
}
subsys_initcall(net_dev_init);//确保NIC设备驱动程序自行注册前net_dev_init会先执行。第七章会说明为啥要这样。
net_dev_init主要部分:
    由两个网络软中断所使用的对应各个cpu的数据结构初始化。
    一些文件会添加到/proc。
    netdev_sysfs_init向sysfs注册为net类,这样会创建/sys/class/net目录。
    net_random_init初始化一个对应各个cpu的种子向量,用于net_random函数产生随机数。
    用于协议无关的母的缓存,以dst_init做初始化,第三十三章会描述。
    协议处理例程向量ptype_base初始化,用于分离入口流量的多路合并传输。第十三章由说明。
    当定义OFFLINE_SAMPLE符号时,内核会建立一个定期执行的函数,已收集设备队列长度的统计数据。参考第十章平均队列长度及拥塞等级计算。
    把一个回调函数注册到有关CPU热插拔事件的通知信息的通知链。
内核的数字可被视为真正随机的程度就称为系统熵。
用户空间辅助程序
在有些情况下,内核会调用用户空间程序以处理事件。
    /sbin/modprobe:当内核需要加载模块时会被调用。
    /sbin/hotplug:当内核侦测到一个新设备插入或拔出时会调用。设备的识别是通过其所插入的总线以及总线规范所定义的相关联ID识别的。
kmod
kmod是内核模块加载程序。
下图是导致内核要求/sbin/modprobe加载一个模块的两个事件实例:
当管理员使用ifconfig配置一张设备驱动程序尚未加载的网卡,如eth0(注意,因为设备驱动程序尚未加载,所以还不存在eth0),则内核向/sbin/modprobe发出请求,以加载名称为"eth0"的模块。
当用tc命令配置一个设备的流量控制时,若涉及了不在内核内的队列规则或分类器,内核会向/sbin/modprobe发送请求以加载相关模块。
热插拔
编译内核模块时,目标文件在/lib/modules/kernel_version/目录下,在同一个目录可以发现两个文件,modules.pcimap核modules.usbmap。这两个文件包含了内核所支持设备的PCI ID核USB ID。当用户空间辅助程序收到一个热插拔设备插入信息时,就会用这些文件找出正确的设备驱动程序。这些文件的填写来自设备驱动程序所提供的ID向量。
虚拟设备
虚拟设备的三种模型:
Linux允许定义多种不同的虚拟设备,以下是一些范例:
    绑定(bonding):虚拟设备可以绑定一组物理设备,使其如同单一设备。
    802.1Q:这是一种IEEE标准,以VLAN包头扩充以太网帧头来建立VLAN
    桥接:桥接接口就是网桥虚拟代表。
    别名接口:原本主要的目的是让一个真实的Ethernet设备横跨几个虚拟接口(如eth0,eth1等),每一个接口都有ip配置。现在,由于代码改进,在同一NIC上配置多个ip时已经不需要定义一个新的虚拟接口。但有时,让一个NIC虚拟出多个NIC可以简化配置。
    普通均衡器:队列规则,用于流量控制。
    隧道接口:IP-over-IP隧道以及GRE协议的实现基础是虚拟设备的建立。
与内核网络协议栈之间的交互
虚拟设备核真实设备与内核的交互有些不同:
    初始化:大多数虚拟设备如同真实设备一样,有一个net_device数据结构。别名设备没有net_device数据结构。
    配置:提供特殊用户空间工具来配置虚拟设备是很常见的事。
    外部接口:每个虚拟设备通常会输出一个文件或一个目录到/proc文件系统。与虚拟设备相关的文件属于额外文件,不会替代与物理设备相关的文件。
    传输:当虚拟设备和物理设备不是一对一时,用于传输的函数可能需要选择所用的真实设备以及其他任务。
    接收:虚拟设备都是软件对象,不参与系统上真实资源(如注册IRQ,分配I/O等)的交互,其流量间接来自真实设备。
    外部通知信息:虚拟设备时实现在真实设备上的,而真实设备对此逻辑毫无所知,因此通知信息需要直面虚拟设备,而不是通过物理设备传递。但是虚拟设备只能接收软件触发的通知信息,硬件触发的则收不到。
通过/proc文件系统调整
/proc/sys/kernel中的文件modprobe和hotplug可以修改前面提到的用户空间辅助程序的路径名称。
在/proc/net中可以找到由net_dev_init通过dev_proc_init和dev_mcast_init创建的文件:
    dev:对每个已注册至内核的网络设备,会显示一些有关接收和传输的统计数据。
    dev_mcast:对每个已注册至内核的网络设备,会显示一些由ip多播使用的参数值。
    wireless:类似dev,对于每个无线设备而言。
    softnet_stat:输出有关网络代码所使用的软件中断的统计数据。参见十二章
内核参数已经逐渐从/proc移除,移到/sys目录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值