Linux 设备管理
设备初始化是我们要分析的第三和第四个大步骤,这个部分要涉及到一些设备驱动的背景知识。
设备管理的目标是能对所有的外设进行良好的读、写、控制等操作。但是如果众多设备没有一个统 一的接口,则不利于开发人员的工作。因此 Linux 采用了类似 UNIX 的方法,使用设备文件来实现这个 统一接口。由此可见,设备文件的相关概念是设备管理的最基础部分。
要让操作系统感知到设备的存在,必须提供一个注册机制,使操作系统能识别设备对应的驱动程序, 目前采用基于主、次设备号的方式来管理设备。Linux 习惯上将设备文件放在目录/dev 或其子目录之下, 设备文件名通常由两部分组成,第一部分通常较短,可能只有 2 或 3 个字母组成,例如普通硬盘如 IDE 接口的为“hd”,SCSI 硬盘为“sd”,软盘为“fd”,并口为“lp”,第二部分通常为数字或字母,用来区 别设备实例。例如/dev/hda,/dev/hdb,/dev/hdc 表示第一、二、三块硬盘;而/dev/hda1、/dev/hda2、/dev/hda3表示第一硬盘的第一、第二、第三分区。
这种机 制就 是 2.4.的版本中的注册与管理方式——devfs 管理方式,如果在编译内核时选中 CONFIG_DEVFS_FS,那么就可以利用这种设备管理方式。devfs 挂载于/dev 目录下,提供了一种类似于 文件的方法来管理位于/dev 目录下的所有设备,我们知道/dev 目录下的每一个文件都对应的是一个设备, 至于当前该设备存在与否先且不论,而且这些特殊文件是位于根文件系统上的,在制作文件系统的时候 我们就已经建立了这些设备文件,因此通过操作这些特殊文件,可以实现与内核进行交互。但是 devfs 文件系统有一些缺点,例如:不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的 U 盘可能对应 sda 有可能对应 sdb;没有足够的主/辅设备号,当设备过多的时候,显然这会成为一个问题; /dev 目录下文件太多而且不能表示当前系统上的实际设备;命名不够灵活,不能任意指定,容易造成设 备之间冲突而不能正常初始化驱动。 本人在构思这本书的时候 devfs 管理方式还在大行其道,但是时隔 3 年,内核源代码中已经不采用这 种技术,转而采用 sysfs 技术。引入了一个新的文件系统 sysfs,它挂载于/sys 目录下,跟 devfs 一样它也 是一个虚拟文件系统,也是用来对系统的设备进行管理的,它把实际连接到系统上的设备和总线组织成一个分级的文件,用户空间的程序同样可以利用这些信息以实现和内核的交互,该文件系统是当前系统 上实际设备树的一个直观反应,sysfs 的工作就是把系统的硬件配置视图导出给用户空间的进程。在 2.6.18 内核中,必须选中 General SetupConfigure Standard Kernel features(For small systems),在 File SystemPseudo filesystems 菜单内部出现“sysfs file system support”。
不管如何进步,其中心思想是建立一种分层的体制,块设备是一种 class,字符设备是一种 class,而 网络设备也是一种 class,驱动程序开发者如果知道自己的设备属于哪一种 class,那么就把其驱动程序挂 到相应的 class 上,让内核为驱动程序分配名字和设备号,如果不确定是哪种 class,还可以自己建立 class 类别。Linux 用户可以到/sys 下观察一下系统中有哪些内核模块及驱动,然后和/dev 下的文件做一个对比 就发现,/sys 目录确实将各种设备进行了归类,条理清晰的多。用户空间的工具 udev 就是利用了 sysfs 提供的信息来实现所有 devfs 的功能的,但不同的是udev 运行在用户空间中,而 devfs 却运行在内核空 间,而且udev不存在 devfs 那些先天的缺陷。很显然,sysfs 将是未来发展的方向。
那么 sysfs 是怎么认出系统中存在的设备以及应该使用什么设备号呢?对于已经编入内核的驱动程 序,当被内核检测到的时候,会直接在 sysfs 中注册其对象;对于编译成模块的驱动程序,当模块载入 的时候才会这样做。一旦挂载了 sysfs 文件系统(挂载到 /sys),内建的驱动程序在 sysfs 注册的数据就可 以被用户空间的进程使用,并提供给 udev 以创建设备节点。
关于设备管理的内容,我只想说这么多,因为要牵扯到许多的配置文件和环境变量,由于每个版本 的 Linux 的设备管理在配置文件和环境变量的设置上多少有些不同,它们的进化又非常快,我觉得只要 不影响本文的理解,我们就先跨过这部分内容吧。
下面我们开始进入内核设备管理系统。
Linux 在设备驱动程序的实现上又分为两层:
- 抽象设备层(又叫核心模块)
- 特定设备驱动程序
抽象硬件层: 这一层主要提供一些设备无关的处理流程,也提供一些公用的函数给底层的 device driver 调用。 它为网络协议提供统一的发送、接收接口。这主要是通过net_device结构。是上层的、与设备无关的, 这部分根据输入输出请求,通过特定设备驱动程序接口,来与设备进行通信。
特定设备驱动程序:是一种下层的、与设备有关的,常称为设备驱动程序,它直接与相应设备打 交道,并且向上层提供一组访问接口; 当一个网络设备的初始化程序被调用时,它返回一个状态指 示它所驱动的控制器是否有一个实例。
那么第三个大步骤就是抽象设备层的初始化。
这由net_dev_init函数完成,此函数由下面的宏修饰, 如下:
subsys_initcall(net_dev_init);这个宏定义请参见前面说的 init.h,它被定义为:define_initcall("4",fn)所以它是在 core_initcall 和fs_initcall之后被调用的。
在 Linux2.4 内核中net_dev_init就是对实际底层网络设备的初始化例程。但是我们要注意的是现在的 这个函数在 Linux2.6 内核中已经不对特定设备进行初始化了,只是为网络设备设置一些基础功能。比如 proc 文件系统、sysfs 系统、全局设备和索引表、设置软中断回调等。不过我个人觉得最重要的是对 queue 的各项成员的初始化。
内核网络初始化函数net_dev_init 分析:

本文详细介绍了Linux设备管理,特别是网络设备的初始化过程。设备管理使用设备文件作为统一接口,通过主次设备号进行管理。Linux内核采用sysfs文件系统替代了旧的devfs,提供更直观的设备管理。网络设备初始化涉及抽象设备层和特定设备驱动程序,其中sysfs在设备注册和设备节点创建中起到关键作用。PCI模块的初始化确保驱动程序与设备正确配对,驱动程序通过probe函数完成设备的具体初始化。文章强调了网络设备接口初始化的重要性,并描述了设备驱动程序加载和初始化的步骤,包括PCI数据库的角色和中断处理的设置。
最低0.47元/天 解锁文章
767

被折叠的 条评论
为什么被折叠?



