购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第3章

最简驱动程序

嵌入式Linux系统设计的一个关键概念就是用户应用与底层硬件的隔离。用户态应用程序不允许直接访问外设寄存器、存储媒介甚至内存。取而代之的是通过内核驱动来访问硬件,通过 内存管理单元 (MMU)来管理内存,应用程序则运行在 虚拟地址空间

这样的隔离提供了健壮性。假设Linux内核的运行是正确的,那么只允许内核操作底层硬件可以防止应用程序恶意或者无意地对硬件设备进行错误的配置,并进一步导致硬件设备处于未知状态。

这样的隔离也提供了可移植性。如果只有内核驱动管理硬件相关代码,将系统从一个硬件平台移植到另一个平台时只需要修改这些驱动就可以了。在不同的硬件平台中,应用程序调用的驱动API是一致的,这就允许应用程序在从一个平台迁移到另一个的时候,几乎可以不必对源代码做修改。

设备驱动可以表现为内核模块,也可以静态构建到内核镜像中。内核默认会将大部分驱动静态构建进去,因此它们会被自动加载。一个内核模块并不一定是设备驱动,这些内核模块仅仅是对内核的一个扩展。内核模块被加载到内核的虚拟地址空间。将设备驱动构建成模块使得开发更加容易,因为加载、测试以及卸载模块都可以在不重启内核的情况下进行。内核模块一般存放在根文件系统的 /lib/modules/<kernel_version>/ 目录。

每个内核模块都有一个 init() 函数和一个 exit() 函数。 init() 函数在驱动加载的时候执行, exit() 函数则在驱动移除的时候被调用。 init() 函数让操作系统知道驱动具备什么样的能力,以及具体事件(比如,将驱动注册到总线、注册一个字符设备等)发生时应该调用驱动的哪个函数。 exit() 函数必须释放所有 init() 函数请求的资源。

module_init() 宏和 module_exit() 宏负责将 init() exit() 函数的符号导出,这样内核代码在加载你的模块时就能够识别这些函数入口。

还有一些宏被用来指定模块的各种属性。这些属性会被打包进模块并可以通过各种工具来访问。描述模块的最重要的宏是MODULE_LICENSE。如果这个宏没有被设置为某种GPL许可证标记,那么当你加载模块时内核就会被污染。内核被污染也就意味着内核处于一种不会被社区支持的状态。大多数内核开发者会忽略涉及被污染内核的故障报告。社区成员在着手分析内核相关的问题之前,可能会要求你先处理被污染的内核。另外,当内核被污染时,某些调试功能和API调用可能会被禁止。 1xTbPZE3Sgj5kLsHoxBKdWehqOLeJPxDwlaQmG2wYv9YhZhfRWdYy79AxdEmOCC3

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开