日期:2014-05-16  浏览次数:20722 次

<Linux内核设计与实现>总结
1."一次做一件事,做到完美"
2.理解内核某部分的捷徑就是对它做一些修改,这样能为开发者揭示仅仅通过看内核代码无法看到的深层机理
3.应用程序通常调用库函数再由库函数通过系统调用界面,让内核代其完成各种不同任务。当一个应用程序执行一条系统调用,我们说内核正在代其执行。在这种情况下,应用程序被称为通过系统调用在内核空间运行,而内核被称为运行于进程上下文。
4.许多操作系统的中断服务程序,包括Linux的,都不在进程上下文中执行。它们在一个与所有进程都无关的,专门的中断上下文中运行。这是为了保证中断服务程序能够在第一时间响应和处理中断请求。
5.Linux是一个单内核,Linux内核运行在单独的地址空间上。
6.内核编程既不能访问C库也不能访问标准的C头文件。内核编程必须使用GNU C。内核编程缺乏像用户空间那样的内存保护机制。内核编程难以执行浮点运算。内核给每个进程只有一个很小的定长堆栈。要考虑可移植性。
7.操作字符串的函数组就位于lib/string.c文件。只要包含<linux/string.h>头文件就可以使用它们。
8.printk()函数负责把格式化好的字符串拷贝到内核日志缓冲区上,这样,syslog程序就可以通过读取该缓冲区来获取内核信息。printk()和printf()之间的一个显著区别在于,printk()允许你通过指定一个标志来设置优先级。
9.内联函数会在它所调用的位置上展开。这么做可以消除函数调用和返回所带来的开销。而且,由于编译器会把调用函数的代码和函数本身一起进行优化,所以有进一步优化代码的可能。但这样做代码会变长,意味着占用更多的内存空间或者占用更多的指令缓存。内联函数必须在使用之前就定义好,否则编译器就没法把这个函数展开。实践中一般在头文件中定义内联函数。
10.gcc编译器支持在C函数中嵌入汇编指令。在偏近体系结构底层或对执行时间要求严格的地方,一般使用的是汇编语言。
11.内核中的内存都不存在分页,也就是说,你每用掉一个字节,物理字节就减少一个字节。
12.用户空间的栈本身比较大,并且可以动态地增长。而内核栈的大小是固定的两页。这就意味着,32位机的内核栈是8KB。
13.进程是正在执行的程序代码的实时结果。
14.系统调用fork()通过复制一个现有的进程来创建一个全新的进程。fork()系统调用从内核返回两次:一次回到父进程,另一次回到新产生的子进程。
15.系统调用和异常处理程序是对内核明确定义的接口。进程只有通过这些接口才能陷入内核执行。
16.Linux的fork()使用写时拷贝页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。
17.线程机制提供了在同一程序共享内存地址空间运行的一组线程。这些线程还可以共享打开的文件和其他资源。
18.Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。线程只是一种进程间共享资源的手段。
19.内核线程:独立运行在内核空间的标准进程,它没有独立的地址空间,只在内核空间运行。
20.创建一个新的内核线程的方法kthread_create()
21.C编译器会在main()函数的返回点后面放置调用exit()函数。
22.进程终结时所需的清理工作和进程描述符的删除被分开执行。在父进程获得已终结的子进程信息后,或者通知内核它并不关注那些信息后,子进程的task_struct结构才被释放。
23.Linux中同时存在子进程链表和ptrace子进程链表。当一个进程的父进程退出后,系统会为它和它的所有兄弟重新找一个父进程。在以前的内核中,这就需要遍历系统所有的进程来找这些子进程。现在的解决办法是在一个单独的被ptrace跟踪的子进程链表中搜索相关的兄弟进程--用两个相对较小的链表减轻了遍历带来的消耗。
24.“反转楼梯最后期限调度算法”--“完全公平调度算法”简称CFS。
25.用asmlinkage限定词来限定系统调用。它是一个编译命令,通知编译器仅从栈中提取该函数的参数。
26.在Linux中,每个系统调用被赋予一个系统调用号,进程不会提及系统调用的名称。
27.中断使得硬件得以发出通知给处理器,中断本质上是一种电信号,由硬件设备发向处理器。处理器接收到中断后,会马上向操作系统反映此信号的到来,然后就由操作系统负责处理这些新到来的数据。硬件设备生成中断的时候并不考虑与处理器的时钟同步--换句话说就是中断随时可以产生。
28.从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入终端控制器的输入引脚中---中断控制器是个简单的电子芯片,其作用是将多路中断管线,采用复用技术只通过一个和处理器相连接的管线与处理器通信。当接收到一个中断后,中断控制器会给处理器发送一个电信号。处理器一经检测到此信号,便中断自己的当前工作转而处理中断。此后,处理器会通知操作系统已经产生了中断,这样,操作系统就可以对这个中断进行适当的处理了。
29。一个设备的中断处理程序是它设备驱动程序的一部分--设备驱动程序是用于对设备进行管理的内核代码。
30.驱动程序可以通过request_irq()函数注册一个中断处理程序(声明在<linux/interrupt.h>中),并且激活给定的中断线,以处理中断。request_irq()函数可能会睡眠,因此,不能在中断上下文或其他不允许阻塞的代码中调用该函数。
31.request_irq()函数会引起堵塞----在注册一个中断处理程序过程中,内核需要在/proc/irq文件中创建一个与中断对应的项。函数proc_mkdir()就是用来创建这个新的procfs项的。proc_mkdir()通过调用函数proc_create()对这个新的procfs项进行设置,而proc_create()会调用函数kmalloc()来请求分配内存。kmalloc()是会睡眠的,因此注册过程中会引起阻塞。
32.cat /proc/cpuinfo看与各个处理器核相关的信息。
33.文件/proc/interrupts是中断报告文件,可以查看中断发生的次数。
34.进程上下文是一种内核所处的操作模式,此时内核代表进程执行。
35.在进程上下文中,可以通过current宏关联当前进程。
36.因为没有后备进程,所以中断上下文不可以睡眠,否则又怎么能再对它重新调度呢?因此,不能从中断上下文中调用某些函数。如果一个函数睡眠,就不能在你的中断处理程序中使用它。
37.