基于Linux系统内核的实习设备驱动程序毕业论文.doc

上传人:精*** 文档编号:827417 上传时间:2023-09-05 格式:DOC 页数:44 大小:217.77KB
下载 相关 举报
基于Linux系统内核的实习设备驱动程序毕业论文.doc_第1页
第1页 / 共44页
基于Linux系统内核的实习设备驱动程序毕业论文.doc_第2页
第2页 / 共44页
基于Linux系统内核的实习设备驱动程序毕业论文.doc_第3页
第3页 / 共44页
基于Linux系统内核的实习设备驱动程序毕业论文.doc_第4页
第4页 / 共44页
基于Linux系统内核的实习设备驱动程序毕业论文.doc_第5页
第5页 / 共44页
点击查看更多>>
资源描述

1、目 录摘 要1ABSTRACT 2前 言3第1章 概述41.1 Linux 的诞生和发展41.1.1 UNIX、MINIX、GNU 和POSIX41.1.2 Linux的开发过程41.2 Linux操作系统51.2.1 Linux内核进程管理61.2.2 Linux内存管理71.2.3 Linux内核的文件系统71.2.4 Linux内核的系统调用7第 2 章 Linux内核以及设备驱动92.1 Linux 内核简介92.2 Linux设备驱动程序92.2.1设备驱动程序的概念92.2.2 Linux驱动程序92.2.3 Linux驱动程序的特点102.2.4 设备号112.3 Linux备驱

2、动的分类122.4 驱动程序的基本结构132.5 驱动程序与外界的接口132.6 安全问题14第3章 Linux字符设备驱动程序的设计163.1设备驱动层次结构163.2 模块分析163.3系统分析173.3.1可安装模块机制173.3.2用户态和内核态173.3.3 I/O 端口173.3.4 内核中的并发193.3.5 内存操作193.3.6设备的访问机制20第 4 章 Linux 设备驱动的实现与调试214.1 字符设备驱动程序的基本数据结构214.1.1 file operations 结构214.1.2 inode结构224.2 设备驱动程序的主要实现234.2.1设备注册234.2

3、.2设备解除注册234.2.3设备打开234.2.4设备释放254.2.5设备读写254.2.6 lseek()操作的实现264.2.7内存获取274.3 驱动程序的编译、加载和卸载274.3.1设备驱动程序的编译274.3.2 设备驱动程序的加载294.3.3 设备驱动程序的卸载304.4 系统调试304.4.1 打印调试304.4.2 ioctl 调试32结束语34参考文献35致 谢36附 录37湖南工程学院毕业设计(论文)Linux 内核实习设备驱动程序摘 要:随着计算机技术和Internet的迅猛发展,操作系统从最初的Dos模式到如今的图形化模式。当前几大主流的操作系统包括Window

4、s、Unix、Linux;可以说Linux是在Unix的基础上发展起来的,而最为用户熟悉的就是微软的Windows操作系统,无论Windows的哪个版本用户群都比较多,但是Windows在服务器方面逊色于Linux,目前大型的应用系统都部署在Unix和Linux操作系统,因为二者的稳定性和安全性非常好。在Linux操作系统中,我认为最核心的就是它的内核部分,内核,是一个操作系统的核心。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。Linux的一个重要的特点就是其源代码的公开性,所有的内核源程序都可以在/usr/src/linux下找到,大部分应用软件也都是

5、遵循GPL而设计的,你都可以获取相应的源程序代码。而内核的处理程序包括很多的设备驱动模块,Linux 系统中设备的基本类型有字符设备、块设备和网络设备三种。相对来说, 字符设备对应的驱动程序最为简单, 但这类设备驱动程序适合于大多数硬件设备, 而且其中的一些方法同样适合块设备和网络设备, 因此从它入手来了解Linux 设备驱动程序的开发很有必要。关键词: Linux;内核;设备驱动程序Linux Kernel Training Device Driver ProgramABSTRACT :With the computer technology and the rapid developmen

6、t of Internet, the operating system from the original Dos mode to graphical mode now. Several of the current mainstream operating systems including Windows, Unix, Linux; can be said that Linux is a Unix-developed on the basis, and most users are familiar with Microsofts Windows operating system, reg

7、ardless of which version of Windows user groups than the more Windows in the server area, however inferior to Linux, the application of the current large-scale systems are deployed in Unix and Linux operating systems, because both the stability and security was very good. In the Linux operating syst

8、em, I think that is the core part of its core, the kernel is the core of an operating system. It is responsible for the process management system, memory, device drivers, files, and network system, determines system performance and stability. Linux as an important feature of the openness of its sour

9、ce code, all the kernel source code can be in / usr / src / linux to find that most applications are designed to follow the GPL, you can obtain the corresponding the source code. And core handling procedures, including a lot of device driver modules, Linux system, the basic types of equipment, chara

10、cter devices, block devices and network equipment in three. Relatively speaking, the character device driver that corresponds to the most simple, but this kind of device drivers for most hardware devices, and some of the method is also suitable for block devices and network equipment, so from its st

11、art to understand the Linux device driver development is necessary.Keywords: Linux; core; device driver前 言以 Linux 为代表的自由操作系统的很多优点之一,是它们的内部是开放给所有人看的。操作系统,曾经是一个隐藏的神秘的地方, 它的代码只局限于少数的程序员, 现在已准备好让任何具备必要技能的人来检查,理解以及修改。Linux 已经帮助使操作系统民主化。Linux 内核保留有大量的复杂的代码,但是,那些想要成为内核 hacker 的人需要一个入口点,这样他们可以进入代码中,不会被代码的复杂

12、性压倒。通常,设备驱动提供了这样的门路。驱动程序在 Linux 内核里扮演着特殊的角色。它们是截然不同的“黑盒子”,使硬件的特殊的一部分响应定义好的内部编程接口,它们完全隐藏了设备工作的细节。 用户的活动通过一套标准化的调用来进行,这些调用与特别的驱动是独立的;设备驱动的角色就是将这些调用映射到作用于实际硬件的和设备相关的操作上。这个编程接口是这样, 驱动可以与内核的其他部分分开建立,并在需要的时候在运行时“插入”。这种模块化使得 Linux 驱动易写,以致于目前有几百个驱动可用。在你学习编写驱动时, 你通常会发现大量有关 Linux 内核的东西。这也许会帮助你理解你的机器是如何工作的,以及为

13、什么事情不是如你所愿的快,或者不是如你所要的进行。我们会逐步介绍新概念,由非常简单的驱动开始并建立它们。硬件如果缺少了驱动程序的“驱动”,那么本来性能非常强大的硬件就无法根据软件发出的指令进行工作,硬件就是空有一身本领都无从发挥,毫无用武之地。这时候,电脑就正如古人所说的“万事俱备,只欠东风”,这“东风”的角色就落在了驱动程序身上。如此看来,驱动程序在电脑使用上还真起着举足轻重的作用。 第1章 概述1.1 Linux 的诞生和发展Linux操作系统是UNIX操作系统的一种克隆版本。它诞生于1991年的10月5日(这是第一次正式向外公布的时间)。以后借助互联网,在全世界各地计算机爱好者的共同努力

14、下,发展成为目前世界上用户最多的一种UNIX操作系统,并且使用人数还在迅猛增加。Linux操作系统的诞生、发展和成长过程依赖于五个重要支柱:UNIX操作系统、MINIX操作系统、GUI计划、POSIX标准和互联网。1.1.1 UNIX、MINIX、GNU 和POSIXUNIX操作系统是美国贝尔实验室的Ken Thompson 和Dennis Ritchie于1969年夏在DEC PDP-7小型计算机上开发的一个分时操作系统。后经Dennis Ritchie于1972提用C语言进行改写,使得UNIX系统在大专院校得到了推广。 MINIX操作系统是由Andrew S. Tanenbaum在1987

15、年编制的,主要用于学生学习操作系统原理。目前主要有两个版本在使用:1.5版和2.0版。最初该操作系统在大学使用是免费的,但其他用户需要付费使用。现在它已经是完全免费的,可以从许多FTP上下载。GNU计划和自由软件基金会(the Free Software Foundation FSF)Richard M. Stallman 于1984年创办的,旨在开发一个免费的、类似UNIX的操作系统GNU系统。到20世纪90年代初,GNU项目已经开发出许多高质量的免费软件,其中包括有名的Emacs编辑系统、BASH shell 程序、GCC 系列编译器程序、GDB 调试程序等。这些软件为Linux操作系统的

16、开发创造一个合适的环境,是Linux能够诞生的基础之一。所以目前许多人都将Linux操作系统称为“GNU/Linux”为操作系统。POSIX(Portable Operating System Interface for Computing Systems)是由IEEE和ISO/IEC开发的一簇标准。到20世纪90年代初,POSIX标准的制定正处于在最后投票敲定的时候。此时Linux刚刚起步。这个标准为Linux提供了极为重要的信息,使得Linux能够在标准的指导下进行开发,做到与绝大多数UNIX系统兼。1.1.2 Linux的开发过程实际上,并没有一个专门的、独立的组织负责开发Linux系统

17、,它是由世界各地的自愿者通过Internet共同开发的,Linux团体大部分通过邮递列表和USENET的消息进行通信,这样任何人都有机会辅助开发和调试Linux的内核、连接新的软件、编写文档和帮助新用户。Linux最强大的生命力正是在于这种公开的开发过程。UNIX是一个简单且非常优秀的模型,在Linux创建之前,UNIX已经有20年的发展历史。Linux从UNIX的各个流派中不断吸取成功经验,抛弃UNIX的缺点,使Linux成为了UNIX系列中的佼佼者。开发商业的UNIX是一个很大的工程,并且为了保证下次操作系统的升级性能,通常有数以百计的程序员、测试员和系统管理员参与,所以商业UNIX那种开

18、发过程使得它的源代码非常复杂。但是,Linux就完全不同,每个人都可以通过Internet 自由获取Linux内核源程序,每个人都可以对源程序加以修改。在使用中如果发现了缺陷或还有什么新的创意,都可以加以改进,用户也可以直接在系统中增加功能,而不用操作系统供应商解释自己的想法。这在源程序不公开的操作系统中是很难办到的。Linux开发团体大部分通过邮递列表USENET的消息组通信。许多协定已经跳过开发过程,如果是一个Linux爱好者想将自己的代码添加到“正式”内核中,只需给Linus Torvalds 发一个E-mail,他就会进行测试,如果测试通过,代码就会被包括进内。进行嵌入式Linux 系

19、统的开发,很大的工作量是为各种设备编写驱动程序。总的来说,实现一个嵌入式Linux 设备驱动的大致流程如下:(1) 查看原理图,理解设备的工作原理。(2) 定义主设备号。(3) 在驱动程序中实现驱动的初始化。如果驱动程序采用模块的方式,则要实现模块初始化。(4) 设计所要实现的文件操作,定义file_operations 结构。(5) 实现中断服务(中断并不是每个设备驱动所必须的)。(6) 编译该驱动程序到内核中,或者用insmod 命令加载。(7) 测试该设备。1.2 Linux操作系统用户应用程序操作系统服务 操作系统内核 硬件系统一个完整可用的操作系统由4部分组成:硬件、操作系统内核、操

20、作系统服务和用户应用程序。如图11所示,用户应用程序是指那些字处理程序、互联网浏览器或用户自行编制的各种应用程序;操作系统服务程序是指向用户提供的服务,被看作是操作系统部分功能的程序。在Linux操作系统上,这些程序包括X窗口系统、shell 图1.1操作系统组成部分命令解释系统以及内核编程接口等系统程。 Linux 内核主要由5个模块构成,它们分别是:进程调度模块、内存管理模块、文件系统模块、进程和通信模块各网络接口模块。进程调度模块用来负责控制进程对CPU资源的使用。所采取的调度策略使各进程能够公平地访问CPU,同时保证内核能及时地执行硬件操作。内存管理模块用于确保所用进程能够安全地共享机

21、器主内存区,同时,内存管理模块还支持虚拟内存管理方式,使Linux的进程可以使用比实际内存空间更多的内存容量。并可以利用文件系统把暂时不用的内存数据块交换到外部存储设备上去,当需要时再交换回来。文件系统模块用于支持对外部设备的驱动和存储。虚拟文件系统模块通过向所有的外部存储设备提供一个通用的文件接口,隐藏了各种硬件设备的不同细节。从而提供并支持与其他操作系统兼容的多种文件系统格式。进程间通信模块子系统用于支持多种进程间的信息交换方式。网络接口模块提供对多种网络通信标准的访问并支持许多网络硬件。内存管理文件系统进程调度网络接口进程间通信虚拟文件系统 图1.2 Linux内核系统模块结构及相互依赖

22、关系1.2.1 Linux内核进程管理内核负责创建和终止进程,并且处理它们和外部世界的联系(输入和输出)。对整个系统功能来讲,不同进程之间的通信(通过信号,管道,进程间通信原语)是基本的,这也是由内核来处理的。另外,调度器,可能是整个操作系统中最关键的例程,是进程管理中的一部分。更广义的说,内核的进程管理活动实现了在一个CPU上多个进程的抽象概念。1.2.2 Linux内存管理计算机内存是主要资源,而使用内存的策略是影响整个系统性能的关键。内核为每个进程在有限可利用的资源上建立了虚拟地址空间。内核不同部分通过一组函数与内存管理子系统交互,这些包括从简单的malloc/free到更稀奇古怪的功能

23、。1.2.3 Linux内核的文件系统Linux从一开始就把外部设备全都当成“文件”处理。Linux常用的文件系统(1) cramfs文件系统它的主要优点是将文件数据以压缩形式存储,在需要运行时进行解压缩。因为是压缩形式存储文件系统,所以不能直接在Flash上运行。虽然这们可以节省Flash空间,但运行文件系统时需要复制大量数据进行RAM中,消耗了RAM空间。(2) ROMFS文件系统ROMFS(Rom File System)是只读文件系统,系统资源占用很小。早期,它是被用在启动盘(光盘或软盘)中,提供一个比普通文件系统(EXT3)更节省空间的文件系统。ROMFS的文件组织方式非常简单,主要

24、是为了对块设备实现高效管理而开发的。只需要使用mount命令将其挂载到任何目录下,就可以对其中之一的文件进行访问。(3) JFFS和 JFFS2文件系统JFFS 和JFFS2的文件格式是专门为Flash存储器设计的,两者具有“损耗平衡特点”,利用这些措施,Flash的寿命得到了大大的提高。JFFS2是压缩的文件格式,在存储空间占用上优于JFFS格式,但因为它是日志式的文件系统,可能会因为日志文件的过度开销而浪费部分Flash空间。虚拟文件系统VFS是物理文件系统与服务之间的接口层,对用户程序屏蔽掉不同文件系统的实现细节,仅给用户提供一个统一、抽象、虚拟的文件系统接口。它通过对每个文件系统的所有

25、细节进行管理,使得不同系统在Linux的其他进程看来都是相同的。它的主要功能如下: 记录可用的文件系统类型; 将设备与文件系统对应联系起来; 处理面向文件的通用操。1.2.4 Linux内核的系统调用系统调用发生在用户进程(比如 emacs)通过调用特殊函数(例如 open)以请求内核提供服务的时候。此时,用户进程被暂时挂起,内核检验用户请求,尝试执行,并把结果反馈给用户进程,接着用户进程重新启动。系统调用的一般过程为:l 通过异常使系统转换到内核模式(这要依靠硬件支持)。进入内核模式可以按内核特权方式进行内存的存取检查,引用栈指针使用内核栈指针,并执行特权指令。l 程序计数器和处理机状态存入

26、此进程(调用的发出者)的堆栈中。l 把系统调用号,存入内核堆栈中。l 执行一段汇编程序来保留通用寄存器。l 调用一个内核例程去执行系统调用。第 2 章 Linux内核以及设备驱动2.1 Linux 内核简介世界各地都有人在钻研Linux内核,大多是在写设备驱动程序。尽管每个驱动程序都不一样,而且你还要知道自己设备的特殊性,但是这些设备驱动程序的许多原则和基本技术技巧都是一样的当你学习编写驱动程序的时候,你也会发现很多关于Linux内核的知识,这对理解你机器怎么工作很有帮助,并且还可以知道为什么你的机器没有希望的那么快,或者为什么不按照你象要它做的那样做。我们先从简单的驱动程序开始,每介绍一些新

27、概念都会看到相关例子代码,这些代码都不需要特殊硬件。2.2 Linux设备驱动程序我们知道,仅仅物理设备与计算机系统简单相连,并不能使外部设备为用户提供各种所需要的操作,在系统中还需为各种设备配备相应的动作程序。除了CPU、内存和少数几个设备外,在程序执行中几乎所有的系统操作最终都要映射到一个物理设备上,对设备的控制操作通常由该设备的特殊可执行代码实现,这些代码就是设备驱动程序。通俗地讲,驱动程序是用来控制计算机外围设备的程。2.2.1设备驱动程序的概念驱动程序,英文名为“Device Driver”,全称为“设备驱动程序”,是一种可以使计算机和设备通信的特殊程序,可以说相当于硬件的接口,操作

28、系统只有通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。因此,驱动程序被誉为“ 硬件的灵魂”、“硬件的主宰”、和“硬件和系统之间的桥梁”。2.2.2 Linux驱动程序在Linux 操作系统中,驱动程序是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,驱动程序是内核的一部分,他完成以下功能:l 对设备初始化和释放;l 对设备进行管理,包括实时参数设置以及提供对设备的操作接口;l 读取应用程序传送给设备文件的数据并回送应用程序请求的数据;l 检测是处理设备出现的错误。应用程序库函数系统调用接口文件子系统进程控制子系统内存管理子系统底层驱动程序物

29、理硬件设备图2.1 Linux 内核体系结构如图2.1所示,应用程序通过Linux 的系统调用与内核通信。由于Linux 中将设备当作文件处理,所以对设备进行操作的调用和对文件操作的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到内核态,通过内核将open()这样的系统调用转换成对物理设备的操作。在Linux 中通过分层实现对物理设备的调用,并使得内核的结构清晰,提高了模块化的独立性。2.2.3 Linux驱动程序的特点因为Linux系统将所有的外围设备都高度抽象成一些字节序列,并且以文件形式来表示这些设

30、备。所以Linux设备驱动程序被集成在内核中,构成了处理或操作硬件控制器的软件模块,在实际处理中,将驱动程序作为常驻内存的低级硬件处理程序共享库,设备驱动程序形成了对设备的抽象处理。也就是说,设备驱动程序是内核中具有高特权级的、常驻内存的、可共享的下层硬件处理例程。设备驱动程序中包含了如何控制这些设备的技术细节,并通过特定的接口导出一个规范的操作集合,内核模块使用规范的设备接口(即字符设备接口和块设备接口),通过文件系统接口把设备操作导出到用户空间程序中。Linux操作系统允许设备驱动程序作为可装载的内核模块进行安装,驱动程序作为模块可以有两种装载方式:一是静态装载,这时驱动模块可以在Linu

31、x操作系统启动时进行装载;二是动态装载,即这些模块可以在Linux操作系统启动后运行中的任何期间动态装载。Linux操作系统可以支持多种设备,设备驱动程序有如下特点:1) 属于内核代码:设备驱动程序是内核的一部分,如果驱动程序出错,则可能导致系统的崩溃。2) 内核接口:设备驱动程序必须为内核或者其子系统提供一个标准接口。比如,终端驱动程序必须为内核提供一个文件I/O接口;SCSI设备驱动程序应该为SCSI子系统提供一个SCSI设备接口,同时,SCSI子系统也必须为内核提供文件的I/O接口及缓冲区。3) 使用内核机制和服务:设备驱动程序使用标准的内核服务进行管理,比如具有统一的内存分配表等。4)

32、 具有可装载性:大多数的Linux操作系统设备驱动程序都可以在需要时再装载进内核,在不需要时从内核中卸载。5) 具有可设置性:Linux操作系统设备驱动程序可以集成为内核的一部分并可以根据需要把其中的某一部分集成到内核中,这只需要在系统编译时进行相应的设置即可实现。6) 动态性:当系统启动并且各设备驱动程序完成初始化后,驱动程序可以维护其控制的设备。如果该设备驱动程序控制的设备不存在,也不影响系统的运行,此时的设备驱动程序只是多占用了一点系统内存。2.2.4 设备号设备由一个主设备号和一个次设备号标识。主设备号唯一标识了设备类型,即设备驱动类型,它是块设备表或字符设备表中设备表项的索引。次设备

33、号仅由设备驱动程序解释,一般用于识别在同一主设备下的若干可能的硬件设备中I/ O 请求所涉及到的那个设备。在建立一个字符驱动时你的驱动需要做的第一件事是获取一个或多个设备编号来使用。为此目的的必要的函数是 register_chrdev_region,在 中声明:int register_chrdev_region(dev_t first, unsigned int count, char *name);这里,first 是你要分配的起始设备编号。first 的次编号部分常常是 0,但是没有要求是那个效果。count 是你请求的连续设备编号的总数。注意, 如果 count 太大,你要求的范围可

34、能溢出到下一个次编号;但是只要你要求的编号范围可用,一切都仍然会正确工作。最后,name 是应当连接到这个编号范围的设备的名子;它会出现在/proc/devices 和 sysfs 中。如同大部分内核函数,如果分配成功进行,register_chrdev_region 的返回值是 0。出错的情况下,返回一个负的错误码,你不能存取请求的区域。如果你确实事先知道你需要哪个设备编号,register_chrdev_region 工作得好。 然而,你常常不会知道你的设备使用哪个主编号;在 Linux 内核开发社团中一直努力使用动态分配设备编号。内核会乐于动态为你分配一个主编号,但是你必须使用一个不同的

35、函数来请求这个分配。int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);使用这个函数,dev 是一个只输出的参数,它在函数成功完成时持有你的分配范围的第一个数。fisetminor 应当是请求的第一个要用的次编号;它常常是 0。count 和 name 参数如同给 request_chrdev_region 的一样。不管你任何分配你的设备编号,你应当在不再使用它们时释放它。设备编号的释放使用:void unregister_chrdev_region(dev_t

36、 first, unsigned int count); 调用 unregister_chrdev_region 的地方常常是你的模块的 cleanup 函数。上面的函数分配设备编号给你的驱动使用,但是它们不告诉内核你实际上会对这些编号做什么。在用户空间程序能够存取这些设备号中一个之前,你的驱动需要连接它们到它的实现设备操作的内部函数上。2.3 Linux备驱动的分类在Linux操作系统下,设备文件主要有3种类型:l 字符设备;l 块设备;l 网络设备。字符设备:通常字符设备都是顺序写入和读出的。当对字符设备发出读/写请求时,实际的硬件I/O将会紧接着执行操作。这样做法,使得字符型设备的I/O

37、操作很快。块设备:块设备主要是面向大量数据传输或慢速设备而设计的,可以节省CPU等待时间。当对块设备进行读/写操作时,首先要开辟一段内存缓冲区,当用户进程对设备的请求能够满足要求时,就返回请求的数据;如果不能,还需要调用请求函数来进行实际的I/O操作。从表面上看,似乎块设备和字符设备的主要区别就是是否开辟缓冲区、是否支持seek(定位)操作。实际上,它们的主要区别是系统的管理方式。块设备的管理方式是为了优化存储,而字符设备的管理方式是为了优化操作。所以,很可能在嵌入式Linux系统中,某些设备既有字符驱动程序,又有块设备驱动程序。网络设备:网络设备在嵌入式Linux系统中比较特殊,它不像字符设

38、备或者是块设备那样,可以通过对应的设备文件节点去访问,内核也不是通过read()、write()等系统调用去访问网络设备。2.4 驱动程序的基本结构Linux 的设备驱动程序有一个相对标准的组织结构,一般可以分为3 个主要组成部分:(1)自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和能否正常工作。如果设备正常则对这个设备及其相关的设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化时被调用一次。(2)服务于I/O 请求的子程序,又称为驱动程序的上半部。调用这部分程序是由于系统调用的结果。这部分程序在执行时,系统仍认为是与进行调用的进程属于同一个进程,只是由用户态变成了核

39、心态,具有进行此系统调用的用户程序的运行环境,因而可以在其中调用sleep()等与进程运行环境有关的函数。(3)中断服务程序,又称为驱动程序的下半部。在Linux 系统中并不是直接从中断向量表调用设备驱动程序的中断服务子程序,而是由Linux 系统来接收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个进程运行时产生,因而在中断服务程序被调用时,不能依赖于任何进程的状态,也就不能调用任何与进程运行环境有关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务子程序时,都带有一个或多个参数,以唯一标志请求服务的。2.5 驱动程序与外界的接口在Linux系统中,无论是

40、字符设备还是块设备的驱动程序,都需要为内核提供相同的调用接口,这样内核才可以用相同的方式处理不同的设备。在Linux系统内部,为每种不同的类型的设备驱动程序维护相应的数据结构,以便定义统一的接口并实现驱动程序的可装载性和动态性。Linux设备驱动程序与外界的接口可以划分为如下3部分:1) 驱动程序与操作系统内核的接口:这部分通过数据结构file_operations来完成。2) 驱动程序与系统引导的接口:驱动程序可以此实现对设备的初始化。3) 驱动程序与设备的接口:这部分描述了驱动程序如何与设备交互,它将与具体设备密切相关。设备驱动程序与外部的接口关系可归纳为下图。操作系统内核接口驱动程序与设

41、备具体设备各设备设备驱动程序接口系统引导数据结构Flie_operations接口 实现 初始化 进行交互图2.2 设备驱动程序与外部的接口关系2.6 安全问题安全性有两方面。一个问题是由于用户对程序的误操作或发掘出错误造成的;另一个问题是由程序员实现的(错误)功能造成的。显然,程序员比普通用户拥有更多的权利。换句话说就是,以root权限运行从朋友那拿来的程序比给他/她一个root外壳要危险得多。尽管访问编译器本质上不是安全性漏洞,但当所编译的代码执行时,还是会出现漏洞;要小心处理模块,因为内核模块可以做任何事。模块比超级用户的外壳的威力还要强大,它的特权是由CPU确认的。所有系统中的安全性检

42、查都是内核代码完成的。如果内核有安全性漏洞,系统就有漏洞。在内核正式发布版本中,只有root可以加载模块;系统调用create_module检查调用进程的用户ID。因此在正式内核中,只有超级用户,或是成功地称为root的闯入者可以利用特权代码的威力。幸亏在编写设备驱动程序或别的模块时,很少需要考虑安全性问题,因为访问块设备的进程已经受到更通用的块设备技术的严格控制了。例如,对于块设备来说,安全是由文件系统节点的权限和mount命令处理的,因此,在实际的块设备驱动程序中通常没有什么好检查的。尽管如此,从收到第三方软件开始,尤其是当软件涉及到内核时,要格外小心;由于每个人都可以访问源代码,都可以改

43、写和重新编译这些东西。如果可以信任发布版中已经编译好的内核,就要避免编译来源不可靠的内核如果你不能以root身份运行编译好的二进制代码,那最好不要运行编译好的内核。例如,有敌意改动过的内核可能允许任何人加载模块,因此通过create_module就可以打开一个不希望出现的后门。如果确实在模块相关部分考虑到安全性问题,我敦促你看一看securelevel内核变量是怎样使用的。很有趣,你可以注意到最近的内核支持在内核编译时可以删除对模块的支持,这样就关闭了所有安全性有关的漏洞。第3章 Linux字符设备驱动程序的设计3.1设备驱动层次结构层次化设计的一个特征是:要逐步构建符号集(Vocabular

44、y)。随着层次的升高,符号集的功能将越来越大。层次化设计的另一个特征是:完全可以在对其上下层透明的条件下替换某一层次。在最理想的情况下,移植层次化的操作系统只需要重写最底层的代码。纯层次化模型实现的执行速度可能会很慢,因为高层必须(间接的)通过一系列连续的低层才能处理完自己的任务N层调用N-1层,N-1层调用N-2层等等,直到实际的工作在0层被处理完成,最后,结果是通过同样的路径反向传递回来。所以在实际设计中为了提高速度,层次化设计通常会包含对某些高层直接和某些低层通信的支持。但是,这样虽然提高了速度,但是却使得各个层次的替换工作更加困难。3.2 模块分析Linux下的设备驱动程序可以按照两种

45、方式进行编译,一种是直接静态编译成内核的一部分,另一种则是编译成可以动态加载的模块。如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态地卸载,不利于调试,所有推荐使用模块方式。 从本质上来讲,模块也是内核的一部分,它不同于普通的应用程序,不能调用位于用户态下的C或者C+库函数,而只能调用Linux内核提供的函数,在/proc/ksyms中可以查看到内核提供的所有函数。 在以模块方式编写驱动程序时,要实现两个必不可少的函数init_module( )和cleanup_module( ),而且至少要包含和两个头文件。在用gcc编译内核模块时,需要加上-DMODULE -D_K

46、ERNEL_ -DLINUX这几个参数,编译生成的模块(一般为o文件)可以使用命令insmod载入Linux内核,从而成为内核的一个组成部分,此时内核会调用模块中的函数init_module( )。当不需要该模块时,可以使用rmmod命令进行卸载,此进内核会调用模块中的函数cleanup_module( )。任何时候都可以使用命令来lsmod查看目前已经加载的模块以及正在使用该模块的用户数。3.3系统分析3.3.1可安装模块机制Linux 的众多优良特性之一就是可以在运行时扩展由内核提供的特性的能力。这意味着你可以在系统正在运行着的时候增加内核的功能( 也可以去除 )。每块可以在运行时添加到内核的代码,被称为一个模块。Linux 内核提供了对许多模块类型的支持,包括但不限于设备驱动。每个模块由目标代码组成( 没有连接成一个完整可执行文件 ),可以动态连接到运行中的内核中,通过 insmod 程序,以及通过 rmmod 程序去连接。内核的划分表示了负

展开阅读全文
相关资源
相关搜索
资源标签

当前位置:首页 > 学术论文 > 毕业论文

版权声明:以上文章中所选用的图片及文字来源于网络以及用户投稿,由于未联系到知识产权人或未发现有关知识产权的登记,如有知识产权人并不愿意我们使用,如有侵权请立即联系:2622162128@qq.com ,我们立即下架或删除。

Copyright© 2022-2024 www.wodocx.com ,All Rights Reserved |陕ICP备19002583号-1 

陕公网安备 61072602000132号     违法和不良信息举报:0916-4228922