《Linux内核情景分析》这本书读过了一遍,不想继续读第二遍了.
《Linux Kernel Development》这本书前后读了3遍,写得实在是好,正所谓"布衣暖,菜根香,好书滋味长".
去书城买来,饱读之后置于书架之上,扮作有学问之人:) 本想买英文影印版,未能寻到,就买本中文的凑合着看,
看完之后发现有几处明显的翻译错误(好在有英文CHM作为对照).技术类书籍一直都是读的英文CHM或PDF,这一本是例外.
《Understanding the Linux Kernel》这本巨作正在拜读之中,这次不再去买中文版了,还是直接读英文原版比较好.
下面是在阅读《Linux Kernel Development》的过程中自认为值得记录的部分,五笔输入的过程中选词时可能会有输入错误,敬请指正!
-------------------------------------------- 华丽的分割线 -----------------------------------------------------
chapter 1
1.当应用程序向内核请求调用一个系统调用时,我们说内核正在代其执行,如果进一步解释,在这种情况下,应用程序被称为通过系统调用在内核空间运行;而内核则被称为运行在进程上下文中.
2. 硬件与内核的交互:当硬件设备想和系统进行交互时,它首先要向CPU发送一个异步的中断信号,然后由CPU去打断内核当前正在执行的工作,中断通常对应着 一个中断号,内核通过这个中断号来查找对应的中断处理程序,并调用这个找到的中断处理程序来处理中断.为了保证同步,内核可以停用中断,也就是忽略某个中 断,既可以停止所有的中断处理程序,也可以有选择性地停止某些中断处理程序。许多操作系统的中断处理程序都不在进程上下文中,而是在一个单独的与所有的进 程都无关的中断上下文中执行,这样做是为了保证中断处理程序在第一时间响应和处理中断信号,并快速退出.
3.任一时刻,CPU的活动范围为以下三者之一:
a.运行于内核空间,处理进程上下文,代表某个特定的进程执行.
b.运行于内核空间,处理中断上下文,与任何进程无关,处理某个特定的中断信号.
c.运行于用户空间,执行用户程序.
4.单内核与多内核:操作系统的内核设计分为两大阵营:单内核和微内核(以及在科研中的外内核)
单 内核:就是把内核在整体上做为一个单独的大过程来实现,并同时运行在一个单独的地址空间中。因此这样的内核通常以单个静态的二进制文件的形式存储于磁盘, 所有内核服务都在这样一个大的内核空间中运行,内核之间的通信是微不足道的,因为大家都运行在内核态,并处于同一地址空间,内核可以直接调用函数(其它的 内核服务中的功能函数),这与用户空间没有什么区别,这种模式的好处在于:简单和高性能。
大部分的UNIX和Linux是单内核系统.Linux同时也吸收了微内核的优点:内核模块化设计,抢占式内核,支持内核线程,以及动态内核模块加载和卸载.
微 内核:微内核并不将内核作为一个单独的大过程来实现,相反,微内核的功能被划分为独立的过程,每个过程叫做一个服务。理想情况下,只有强烈请求特权服务的 服务器运行在特权模式下,其它的服务都运行在用户空间.不过所有的服务都保持独立并运行在各自的地址空间,因此就不能像单内核那样直接调用函数,而是通过 消息传递处理微内核服务之间的通信:系统采用进程间通信(IPC)机制,各种服务器之间通过IPC机制互通消息,互换服务.服务器的各自独立有效地避免了 一个服务器的失效祸及另一个.Windows和Max OS X 都是微内核.Windows NT内核和Mac OS 的内核都将所有的内核服务程序运行于内核特权模式下,这一点违背了微内核的设计思想,但是减少了内核服务之间的通信之间的消息机制产生的开销.
5.Linux内核并不区分进程和线程,对于内核来说,只有进程,而且所有的进程都一样,只不过是有的进程共享一些资源而已.
6.Linux内核的版本号:x.y.z
x:是主版本号;y:从版本号;z:修订版本号
z:如果为偶数,那么它是一个稳定的版本;如果为奇数,那么它是一个开发版.
x.y 用于描述内核系列.
chapter 2
7.内核源码文件结构:
arch: 特定体系结构的源码
crypto: Crypto API
Documentation: 内核源码文档
drivers: 设备驱动程序
fs: VFS和各种文件系统
include: 内核头文件
init: 内核引导和初始化
ipc: 进程间通信代码
kernel: 内核核心子系统
lib: 通用内核函数
mm: 内存管理子系统和VM
net: 网络子系统
scripts: 编译内核所用的脚本
secrity: Linux安全模块
sound: 语音子系统
usr: 早期用户空间代码(所谓的initramfs)
8.内核中的内核空间都不分页,所以,如果内核空间使用了一个字节的内存,那么实际的可用的物理内存就少了一个字节。
9.在内核中没有内存保护机制.
10. 不要轻易在内核中使用浮点数.在用户空间进行浮点数操作时,内核会完成从整数操作到浮点数操作的模式转换,在执行浮点数操作时到底会做些什么,因体系结构 的不同,内核的选择也会不同,但是内核通常捕获陷阱并做相应的处理.和用户空间进程不同,内核并不能完美支持浮点操作,因为它本身不能陷入.在内核使用浮 点数时,除了要人工保存和恢复浮点计数器,还有其它的一些琐碎的事情要做.所以:不要在内核中使用浮点数.
11.内核开发中,不能使用内核源代码之外的其它的外部库文件.
12.内核中没有printf函数,但是有printk函数可以用于打印调试信息.
13. 内核的栈空间很小:内核栈的准确大小随体系结构而变.在X86系统中,栈的大小可以在编译时配置,可以是4KB,也可以是8KB.从历史上说,内核栈的大 小是两页,这也就意味着,在32位系统上内核栈是8K,在64位系统上,内核栈是16K,这是固定不变的,每个处理器都有自己的栈.
14.硬件中断是异步到来的,由CPU发送给内核,完全不顾及内核当前的操作.
15.Linux内核中常用的用于解决并发产生的竞争的办法是:自旋锁和信号量.
chapter 3
15.进程:就是包含各种资源的处于执行期的程序.
16.线程:进程中的活动对象.每个线程都有一个独立的程序计数器,进程栈和一组进程寄存器.
17.内核调度的是线程而不是进程.
18.Linux中,进程与线程并不特别进行区分,对于内核而言,线程只不过是一种特殊的进程而已.
19.进程的5种状态:
a. TASK_RUNNING(运行状态)--进程是可以执行的,它或者正在执行,或者在运行队列中等待执行,这是进程在用户空间中执行的唯一状态,也可以应用到内核空间中正在执行的进程.
b. TASK_INTERRUPTIBLE(可中断)--进程正在睡眠(也就是说它被阻塞),等待某些条件的达成.一旦这些条件达成,内核就会把进程设置为运行,处于此状态的进程也会因为收到信号而提前被唤醒而投入运行.
c. TASK_UNINTERRUPTIBLE(不可中断)--除了不会因为接收到信号而被唤醒而投入运行之外,这个状态与 TASK_INTERRUPTIBLE(可中断)状态相同.这个状态通常在进程正在等待地不受干扰或等待事件很快就会发生时,由于此状态不对信号进行响 应,所以,较之TASK_INTERRUPTIBLE(可中断)使用得比较少.
d. TASK_ZOMBIE(僵死)--该进程已经结束,但是父进程还没有调用wait4()系统调用,为了父进程能够获知它的消息,子进程的进程描述符仍然被保留着。一旦父进程调用了wait4,该僵死的子进程的进程描述符就会被释放.
e. TASK_STOPPED(停止)--进程停止执行:进程没有投入运行,也不能投入运行.通常这种状态发生在接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信号的时候,此外,在调试期间接收到的任何信号,都会使进程进入这种状态.
20.UNIX创建进程的方式:
许多其它的操作系统都提供了spawn进程的机制: