您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > Linux内核驱动模块编程指南
PeterJaySalzmanMichaelBurianOriPomerantzCopyright©2001PeterJaySalzmanTheLinuxKernelModuleProgrammingGuideisafreebook;youmayreproduceand/ormodifyitunderthetermsoftheOpenSoftwareLicense,version1.1.Youcanobtainacopyofthislicenseat@dirac.org.ThiswillallowforthemergingofupdatesandprovideconsistentrevisionstotheLinuxcommunity.Ifyoupublishordistributethisbookcommercially,donations,royalties,and/orprintedcopiesaregreatlyappreciatedbytheauthorandtheLinuxDocumentationProject(LDP).ContributinginthiswayshowsyoursupportforfreesoftwareandtheLDP.Ifyouhavequestionsorcomments,pleasecontacttheaddressabove.TableofContentsForeword1.作者声明2.版本和注意3.感谢4.译者注1.Introduction1.1.什么是内核模块?1.2.内核模块是如何被调入内核工作的?1.2.1.在开始前1.2.1.1.内核模块和内核的版本问题1.2.1.2.使用X带来的问题1.2.1.3.编译相关和内核版本相关的问题2.HelloWorld2.1.Hello,World(part1):昀简单的内核模块2.1.1.介绍printk()2.2.编译内核模块2.3.HelloWorld(part2)2.4.HelloWorld(part3):关于__init和__exit宏2.5.HelloWorld(part4):内核模块证书和内核模块文档说明2.6.从命令行传递参数给内核模块2.7.由多个文件构成的内核模块2.8.为已编译的内核编译模块3.Preliminaries3.1.内核模块和用户程序的比较3.1.1.内核模块是如何开始和结束的3.1.2.模块可调用的函数3.1.3.用户空间和内核空间3.1.4.命名空间3.1.5.代码空间3.1.6.DeviceDrivers3.1.6.1.MajorandMinorNumbers4.CharacterDeviceFiles4.1.字符设备文件4.1.1.关于file_operations结构体4.1.2.关于file结构体4.1.3.注册一个设备4.1.4.注销一个设备4.1.5.chardev.c4.1.6.为多个版本的内核编写内核模块5.The/procFileSystem5.1.关于/proc文件系统6.Using/procForInput6.1.使用/proc作为输入7.TalkingToDeviceFiles7.1.与设备文件对话(writesandIOCTLs)8.SystemCalls8.1.系统调用9.BlockingProcesses9.1.阻塞进程9.1.1.EnterSandman10.ReplacingPrintks10.1.替换printk10.2.让你的键盘指示灯闪起来11.SchedulingTasks11.1.任务调度12.InterruptHandlers12.1.InterruptHandlers12.1.1.InterruptHandlers12.1.2.Intel架构中的键盘13.SymmetricMultiProcessing13.1.对称多线程处理14.CommonPitfalls14.1.注意A.Changes:2.0To2.2A.1.从2.0到2.2的变化A.1.1.从2.0到2.2的变化B.WhereToGoFromHereB.1.为什么这样写?IndexListofExamples2-1.hello-1.c2-2.一个基本的Makefile2-3.hello-2.c2-4.两个内核模块使用的Makefile2-5.hello-3.c2-6.hello-4.c2-7.hello-5.c2-8.start.c2-9.stop.c2-10.Makefile4-1.chardev.c5-1.procfs.c6-1.procfs.c7-1.chardev.c7-2.chardev.h7-3.ioctl.c8-1.syscall.c9-1.sleep.c10-1.print_string.c10-2.kbleds.c11-1.sched.c12-1.intrpt.cForeword1.作者声明《Linux内核驱动模块编程指南》昀初是由OriPomerantz为2.2版本的内核编写的,后来,Ori将文档维护的任务交给了PeterJaySalzman,Peter完成了2.4内核版本文档的编写,毕竟Linux内核驱动模块是一个更新很快的内容。现在,Peter也无法腾出足够的时间来完成2.6内核版本文档的编写,目前该2.6内核版本的文档由合作者MichaelBurian完成。2.版本和注意Linux内核模块是一块不断更新进步的内容,在LKMPG上总有关于是否保留还是历史版本的争论。Michael和我昀终是决定为每个新的稳定版本内核建立一个新的文档分支。也就是说LKMPG2.4.x专注于2.4的内核,而LKMPG2.6.x将专注于2.6的内核。我们不会在一篇文档中提供对旧版本内核的支持,对此感兴趣的读者应该寻找相关版本的文档分支。在文档中的绝大部分源代码和讨论都应该适用于其它平台,但我无法提供任何保证。其中的一个例外就是Chapter12,中断处理该章的源代码和讨论就只适用于x86平台。3.感谢感谢下列人士为此文档提供了他们宝贵的意见。他们是:IgnacioMartin,DavidPorter,DanielePaolo,Scarpazza和DimoVelev。4.译者注我,译者,名叫田竞,目前是一名在北京邮电大学就读的通信专业的大学生。自高中起我就是Linux的爱好者并追随至今。我喜欢Linux给我带来的自由,我想大家也一样。没有人不向往自由。我学习内核模块编写时昀初阅读的是Orelly出版社的使用2.0版本的内核的书籍,但如同我预料的一样,书中的许多事例由于内核代码的变化而无法使用。这让想亲自体验内核模块的神秘的我非常苦恼。我在Linux文档计划在上海的镜像站ldp.linuxforum.net上找到了这篇文档。受原作者Ori的鼓励,基于上次完成的LKMPG2.4的,内容有稍许的改变和扩充。应该是目前昀新的了。翻译的方式有所改变,在基于LDP认可的docbook格式上翻译,通过docbook2html转换为附件中的html文档。由于对docbook不是很熟悉,其中的一些标题尚未翻译,而且可能破坏了原有的tag,导致html出现一些错误显示,但总体来说很少。修改了很多2.4中的错别字。学习并分享学习的过程是我翻译的昀终目的。Chapter1.Introduction1.1.什么是内核模块?现在,你是不是想编写内核模块。你应该懂得C语言,写过一些用户程序,那么现在你将要见识一些真实的东西。在这里,你会看到一个野蛮的指针是如何毁掉你的文件系统的,一次内核崩溃意味着重启动。什么是内核模块?内核模块是一些可以让操作系统内核在需要时载入和执行的代码,这同样意味着它可以在不需要时有操作系统卸载。它们扩展了操作系统内核的功能却不需要重新启动系统。举例子来说,其中一种内核模块时设备驱动程序模块,它们用来让操作系统正确识别,使用安装在系统上的硬件设备。如果没有内核模块,我们不得不一次又一次重新编译生成单内核操作系统的内核镜像来加入新的功能。这还意味着一个臃肿的内核。1.2.内核模块是如何被调入内核工作的?你可以通过执行lsmod命令来查看内核已经加载了哪些内核模块,该命令通过读取/proc/modules文件的内容来获得所需信息。这些内核模块是如何被调入内核的?当操作系统内核需要的扩展功能不存在时,内核模块管理守护进程kmod[1]执行modprobe去加载内核模块。两种类型的参数被传递给modprobe:一个内核模块的名字像softdog或是ppp。通用识别符像char-major-10-30。当传递给modprobe是通用识别符时,modprobe首先在文件/etc/modules.conf查找该字符串。如果它发现的一行别名像:代码:aliaschar-major-10-30softdog它就明白通用识别符是指向内核模块softdog.o。然后,modprobe遍历文件/lib/modules/version/modules.dep来判断是否有其它内核模块需要在该模块加载前被加载。该文件是由命令depmod-a建立,保存着内核模块的依赖关系。举例来说,msdos.o依赖于模块fat.o内核模块已经被内核载入。当要加载的内核模块需要使用别的模块提供的符号链接时(多半是变量或函数),那么那些提供这些所需符号链接的内核模块就被该模块所依赖。昀终,modprobe调用insmod先加载被依赖的模块,然后加载该被内核要求的模块。modprobe将insmod指向/lib/modules/version/[2]目录,该目录为默认标准存放内核模块的目录。insmod对内核模块存放位置的处理相当呆板,所以modprobe应该很清楚的知道默认标准的内核模块存放的位置。所以,当你想要载入一个内核模块时,你可以执行:代码:insmod/lib/modules/2.5.1/kernel/fs/fat/fat.oinsmod/lib/modules/2
本文标题:Linux内核驱动模块编程指南
链接地址:https://www.777doc.com/doc-5018174 .html