《LINUX设备驱动程序》学习笔记 ——01

发布时间 2023-09-14 16:28:18作者: 成信吴彦祖(略胜亿筹)

1. 关于内核并发

  从2.6版本的内核开始,linux系统已经是可抢占式的任务调度,在此之前只有SMP系统(对称多处理器)才会有的并发问题,在2.6版本内核之后的单核处理器也会面对该问题。

  很多程序员面对并发问题有一个常见的错误:“认为没有睡眠状态(或者阻塞)的进程就不会触发并发”。这即使放在2.6以前的内核(非抢占式内核)中都是错误的,内核代码(几乎)始终不能假定在给定代码段中能够独占处理器。若编写代码不注意并发问题,将可能导致出现很难调试的灾难性后果。

2. 核心模块与应用程序的对比

  在同样是C编程的驱动和应用程序中,驱动程序中具有一些特有的如 “printk”、“moudle init” 等函数及大量宏,而应用程序能调用的各种C库函数内核驱动程序却无法调用。模块仅仅被链接到内核,因此它能调用的函数仅仅是由内核导出的那些函数,而不存在任何可链接的函数库。

  内核模块只能使用作为内核一部分的函数。内核相关的任何内容都在我们安装并配置好的年内和源代码树的头文件中声明。其中,大多数相关头文件保存在 include/linux 和 include/asm 目录中。

  除此之外,应用程序发生的任何段错误都是无害的,并且能够通过调试器跟踪到源代码中的问题所在。而内核错误即使不影响整个系统,也会杀死该进程。(内核错误也是可以跟踪的)。

3. LINUX系统中的用户空间和内核空间(两个极端)

  当前的CPU至少有两个以上的保护级别,而在LINUX系统中只有两个级别:最高级别——超级用户态(内核运行,可进行所有操作),最低级别——用户态(应用程序运行,处理器控制在对硬件的直接访问及对内存的非授权访问)。更重要的是,这两个模式都有自己的内存映射(地址空间)!

  下图是应用程序触发的两个状态的切换。

                

4. 带下划线(__)前缀的函数(谨慎调用)

  在内核API中,如果看到前缀为 __ 的函数,具有这种名称的函数通常是接口的底层组件,应当谨慎使用。(双下划线告诉程序员:谨慎调用,否则后果自负)。

5. 内核栈空间的使用

  内核栈空间非常的小,通常和4096字节大小的页那样小,栈是用来保存函数调用历史以及活动函数中的自动变量的,我们的函数必须和整个内核调用链一同共享这个栈,因此避免在驱动程序中声明大的自动变量。若需要用到大的数据及结构,应当在调用时动态分配。