Linux内核设计与实现读书笔记
前言
阅读经典书籍《Linux内核设计与实现》,对模糊的地方,进行笔记。
一、Linux内核简介
- 每个处理器在任何指定时间点上的活动必然概括为下列三者之一:
- 运行于用户空间,执行用户进程;
- 运行于内核空间,处于进程上下文,代表某个特定的进程执行;
- 运行于内核空间,处于中断上下文,与任何进程无关,处理某个特定的中断;
二、从内核出发
- 对于条件选择语句,gcc内建了一条指令用于优化,在一个条件中经常出现,或者该条件很少出现的时候,编译器可以根据这条指令对条件分支选择进行优化,内核将该指令封装成了宏,比如likely和unlikely。
三、进程管理
- Linux通过slab分配器分配task_struct结构体,这样能够达到对象复用和缓存着色的目的;
- TASK_RUNNING使用户空间中执行的唯一的可能的状态;
- fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符;内核有意选择让子进程首先执行,因为子进程一般 会马上执行exec()函数,这一可以避免写时拷贝的开销,因为父进程如果执行,则写入时候,需要拷贝一份,子进程再执行时候,该mm会被再改写;
- vfork()除了不拷贝父进程的页表之外,如fork()的功能相同。子进程作为父进程的一个单独的线程在他的地址空间中运行,父进程会被阻塞,知道子进程退出或者执行exec()。子进程不能向地址空间中写入。vfork()出现时候,fork()还没有出现写时拷贝的技术;
- 内核线程和普通线程的区别在于内核线程没有独立的地址空间(实际上指向地址空间的mm指针被设置为NULL).
- 进程终结之后的流程:do_exit()
- 将task_struct中的标志成员设置为PF_EXITING;
- 检查删除定时器;
- 检查记账功能;账单记录包含了内核为该进程所维护的多种信息,包括终止状态以及进程消耗的CPU时间;
- 释放mm;
- 离开IPC信号队列;
- 减少(释放)文件以及文件描述符的引用;
- exit_notify()向父进程发送信号,将进程状态设置为EXIT_ZOMBIE;
- schedule()切换到新的进程;
- 父进程的wait()函数用来删除进程描述符以及释放task_struct占用的slab高速缓存;
- 孤儿进程的处理:
- 通过find_new_reaper()为子进程寻找养父,养父最终处理回收工作;其中涉及pid_namespace的概念需要了解;
四、进程调度
- nice值的范围是-20~+19, 默认值为0, 越大的nice值意味着更小的优先级;实时优先级的变化范围为0到99, 包括0和99,越高的优先级数值意味着进程的优先级越高;任何实时进程的优先级都高于普通进程;