第一章 绪论(2)
最后更新于:2022-04-01 20:24:06
### 五、Unix内核概述:
Unix内核提供了应用程序可以运行的执行环境。因此,内核必须实现一组服务及相应的接口,应用程序使用这些接口,而且通常不会与硬件资源直接交互。
### 进程/内核模式:
所有标准的Unix内核都仅仅利用了内核态和用户态。
一个程序执行时,大部分时间都处在用户态下,只有需要内核所提供的服务时才切换到内核态。当内核满足了用户程序的请求后,便使程序回到用户态下。
内核本身不是进程,而是进程的管理者。
Unix系统包括几个称为内核线程的特权进程,它们通常在系统启动时创建,并以内核态运行在内核地址空间,一直处于活跃状态直到系统关闭。
### 进程实现:
每个进程由一个进程描述符表示。
当内核暂停一个进程的执行时,就把几个相关处理器寄存器的内容保存在进程描述符中。当内核决定恢复执行一个进程时,它用进程描述符中合适的字段来装载CPU寄存器,由于程序计数器中所存储的值指向下一条将要执行的指令,所以进程从它停止的地方恢复执行。
Unix内核可以区分很多等待状态,这些等待状态由进程描述符队列实现。每个队列对应一组等待特定事件的进程。
### 可重入内核:
可重入,意味着若干进程可以同时在内核态下执行,但在每个处理器上只有一个进程在真正运行,其它则可能在等待执行或处于阻塞状态。
如果一个硬件中断发生,可重入内核能挂起当前正在执行的进程,即使这个进程处于内核态,这样可以提高发出中断的设备控制器的吞吐量。
###
### 进程地址空间:
在用户态下运行的进程涉及到私有栈、数据区和代码区。
在内核态下运行的进程,访问内核的数据区和代码区,但使用另外和私有栈。
如果一个程序由几个用户同时使用,则这个程序只被装入内存一次,其指令由所需要它的用户共享,当然,其数据不被共享。
进程间也能共享部分地址空间,以实现一种进程间的通信。
###
### 同步和临界区:
实现可重入内核需要利用同步机制,因为如果当内核控制路径对某个内核数据结构进行操作时被挂机,那么,其它内核控制路径就不应当再对该数据结构进行操作。
对全局变量的安全访问通过原子操作来保证。
如果内核支持抢占,如Linux,那么在应用同步机制时,确保进入临界区前禁止抢占,退出临界区时启用抢占。
信号量:
可以把信号量看成一个对象,其组成如下:
* 一个整数变量
* 一个等待进程的链表
* 两个原子方法:down()和up()
每个要保护的数据结构都有它自己的信号量,其初始值为1。当内核控制路径希望访问这个数据结构时,它在相应的信号量上执行down()方法,若信号量的当前值不是负数,则允许访问这个数据结构,否则,把执行内核控制路径的进程加入到这个信号量的链表并阻塞该进程。当另一个进程在那个信号量上执行up()方法是,允许信号量链表上的一个进程继续执行。
自旋锁:
自旋锁与信号量非常相似,但没有进程链表;当一个进程发现锁被另一个进程锁着时,它就不停的“旋转”,执行一个紧凑的循环指令直到锁打开。
自旋锁在单处理器环境下是无效的。因为:当内核控制路径试图访问一个上锁的数据结构时,它开始无休止循环,则内核控制路径可能因为正在修改受保护的数据结构而没有机会继续执行,也没有机会释放这个自旋锁,最后的结果可能是系统挂起。
Linux使用一个名为init的特殊系统进程,它在系统初始化的时候被创建。当一个进程终止时,内核改变其所有现有子进程的进程描述符指针,使这些子进程成为init的孩子。Init监控所有子进程的执行,并且按常规发布wait4()系统调用,除掉所有僵死的进程。
';