驱动程序工作在内核空间,而应用程序一般工作于用户状态下。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。设备驱动程序在整个计算机系统中的结构分布如图8-1所示。
Linux设备驱动开发调试有两种方法:一种是直接编译到内核,随同Linux启动时加载,启动内核时就会驱动此硬件设备。这种方法称为静态链接。另一种是编译为可加载模块(Loadable Kernel Modules)的形式,编译生成一个.o文件。当应用程序需要时再动态加载进内核空间运行,这种方法称为动态链接。Linux提供了一批管理内核模块的命令,主要有lsmod、insmod和rmmod等。lsmod命令用于查看当前内核加载的模块信息;insmod命令将编译的模块直接插入内核,如果出现故障,可以使用rmmod命令从内核卸载模块,而不需要重新启动内核。1smod命令执行的结果如图8-2所示。
图8-1 计算机体系结构
图8-2 1smod命令执行的结果
其中,第1列是模块的名称,第2列是模块的大小,第3列是当前模块使用的数量。
设备驱动是直接操纵硬件的程序,在开发阶段容易因为编写不当而影响系统的正常运行,所以一般把设备驱动程序制作成动态加载的模块,这样既可以增强系统的稳定性,又能避免反复编译内核,提高驱动程序的调试效率。
Linux设备驱动程序一般由3个部分组成。(www.xing528.com)
1)自动配置和初始化子程序。本部分负责检测所要驱动的硬件设备是否存在和能否正常工作。如果设备正常,则对这个设备及其相关的设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化时被调用一次。
2)服务于I/O请求的子程序。这部分又称为驱动程序的上半部。调用这部分程序是系统调用的结果。这部分程序在执行时与进行调试的进程仍然属于同一进程,只是将用户态切换成内核态。它具有进行此系统调用的用户程序的运行环境。在这部分可以调用sleep()等与进程运行环境有关的函数。
3)中断服务程序。本部分又称为驱动程序的下半部。在Linux系统中并不是直接从终端向量表调用设备驱动程序的中断服务子程序,而是由Linux系统来接收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个程序运行中产生,在终端服务程序被调用时,不能依赖于任何进程的状态,不能调用任何与进程运行环境有关的函数。
Linux系统为每个设备分配了一个主设备号与次设备号。主设备号唯一标识了设备类型,次设备号用于标识使用同一个设备驱动程序的不同硬件设备。由同一个设备驱动控制的所有设备具有相同的主设备号。系统中的每种设备都用一种特殊的设备相关文件来表示。块设备和字符设备的设备相关文件可以通过mknod命令来创建,并使用主从设备号来描述此设备。网络设备也用设备相关文件来表示,但当Linux寻找和初始化网络设备时才建立这种文件。在驱动程序中,可以使用下列宏获得驱动的设备号。
如果想把设备号转换成dev_t类型,可以使用下面的函数。
驱动程序和应用程序不同。应用程序一般有一个main()函数,从头到尾执行一个任务;驱动程序没有main()函数,是通过使用宏module_init将初始化函数加入到内核全局初始化函数列表中,然后在内核初始化时执行驱动的初始化函数,完成驱动的初始化和注册。之后,驱动程序便停止,等待被应用软件调用。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。