《深入理解Linux网络内幕》学习笔记二:网络设备初始化

网络设备初始化

        如果要使一个网络设备可用,它就必须能被内核正确识别并且与正确的设备驱动关联起来。首先,设备驱动既可以做为内核模块动态加载,也可以是内核的一个静态组件。其次,设备可以在启动时识别,也可以在运行时加载识别(热插拔设备 USB PCI IEEE...)
 
静态编译的设备驱动/启动识别的设备注册和初始化
下图为系统初始化流程
(内核子系统和静态编译的设备驱动都在do_initcalls中初始化,另外parse_args处理系统启动程序lilo/grub传递给内核的参数,init_IRQ/softing_init初始化硬件中断
和软件中断,free_init_mem会释放这些不再使用的代码所占用的内存)
启动识别的设备注册和初始化大概分为三步;
1)硬件初始化 ---由设备驱动在总线(pci,usb)的协调下完成,主要分配中断号和i/o地址。
2)软件初始化 ---在设备可用前需要配置一些参数,如ip地址
3)功能初始化 ---与设备相关,如流量控制
1 2在后几章会具体说到,这里只简单提下3,代码如下;
static in__init net_dev_init{
...
}
subsys_initcall(net_dev_init)
net_dev_init中包含如下功能的初始化
        初始化cpu相关数据结构,用于网络软中断
        调用dev_proc_init,dev_mcast_init在/proc下增加相应的文件
        调用netdev_sysfs在/sys下增加相应配置文件
        调用net_random_init初始化cpu种子数组,这些数组用于在net_random中生成随机数
        调用dst_init初始化dst
        初始化网络处理函数数组ptype_base,这些函数用来多路分解接收到的包
        在通知链表上注册回调函数用于接收cpu热插拔事件
除了上述初始化,对于网络设备来说更重要的是 初始化它的net_device结构,这个会在第8章详细讲
 
动态加载设备/设备驱动
讲动态加载之前先介绍2个用户空间程序和1个内核函数
/sbin/modprobe  在内核需要加载某个模块时调用,判断内核传递的模块是不是/etc/modprobe.conf文件中定义的别名
/sbin/hotplug   在内核检测到一个新设备插入或拔出系统时调用,它的任务是根据设备标识加载正确的驱动
内核函数call_usermodehelper  上面两个用户进程统一由这个函数调用,其中参数arg[0]指示call_usermodehelper调用哪个用户进程,arg[1]指示call..使用哪个配
置脚本,流程详见下图;
《深入理解Linux网络内幕》学习笔记二:网络设备初始化_第1张图片
实际上看懂了上面所说的,动态加载的概念应该很清楚了,最后再说说使用场景
1)以模块方式加载
        kmod模块加载器允许内核组件通过调用request_module请求加载某个模块
        举个例子;如果系统管理员使用ifconfig配置某个网卡,但这个网卡驱动还没有加载,如eth0,内核就会给/sbin/modprobe发送一个请求,让它加载名称为
eth0的模块。如果/etc/modprobe.conf中包含“alias eth0 xxx”的字符,/sbin/modprobe就会尝试加载xxx.ko模块。
        module_param 宏定义在引入sysfs后可以通过文件来访问得到模块参数
        模块选项有三项 , 第一项参数名称,第二项参数类型,第三项表示参数作为文件在sys文件系统中所有的权限。
        每个模块都会在sys/modules下生成对应的目录,通过目录下的文件可以获取模块参数。

2)pnp热插拔
        hotplug允许内核检测热插拔设备的插入和拔出并通知用户进程(/sbin/hotplug),用户进程根据这些通知来加载相应的驱动
        在编译内核时,会在kernel目录下生成modules.pcimap和modules.usbmap两个文件,这两个文件分别包含了内核所支持设备的pci id和usb id,文件中还包
含于每个设备的id相对应的内核模块名称,当用户进程收到内核关于pnp的通知后,会使用这个文件来查找正确的设备驱动

你可能感兴趣的:(《深入理解Linux网络内幕》学习笔记二:网络设备初始化)