第3章 进程管理
3.1 进程
1、进程
进程就是处于执行期的程序。
进程包括:
实际上,进程就是正在执行的程序代码的实时结果
2、执行线程
进程提供两种虚拟机制:
在线程之间可以共享虚拟内存,但每个都拥有各自的虚拟处理器。
3、fork系统调用 该系统调用通过复制一个现有进程来创建一个全新的进程。 在返回点的相同位置上 fork()实际上是由clone()系统调用实现的。
3.2 进程描述符及任务结构
1、内核把进程的列表存放在叫做任务队列的双向循环链表中。
2、进程描述符中包含一个具体进程的所有信息。
3、进程描述符中包含:
3.2.1 分配进程描述符
1、Linux以通过slab分配器分配task_ struct结构,这样能达到对到对象复用和缓存着色的目的。
2、struct_ thread_ info在文件<asm/thread_ info.h>中定义。
3、每个任务的thread_info结构在他的内核栈的尾端分配。
3.2.2 进程描述符的存放
1、内核通过一个唯一的进程标识值或PID来标识每个进程。
2、硬件体系结构不同,该宏的实现也不同。
3.2.3 进程状态
进程描述符中state域描述了进程的当前状态。
五种进程状态:
3.2.4 设置当前进程状态
set_ task_ state(task,state)函数:
3.2.5 进程上下文
3.2.6 进程家族树
1、Unⅸ系统的进程之间存在—个明显的继承关系。
2、init进程的进程描述符是作为init_task静态分配的。
3、for_ each_ process(task)宏提供了依次访问整个任务队列的能力。
3.3 进程创建
产生进程的机制:
3.3.1 写时拷贝
1、Linux的fork()使用写时拷贝页实现——让父进程和子进程共享同一个拷贝。
fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符。
3.3.2 fork()
1、通过clone()系统调用实现fork(),clone()去调用do_ fork()。
2、copy_ process()完成的工作:
3.3.3 vfork()
1、vfork()与fork()很类似,实现是通过向clone()系统调用传递一个特殊标志来进行。
2、好处是不用拷贝父进程的页表项,不过理想情况下,系统最好不要调用vfork()。
3.4 线程在Linux中的实现
1、线程机制提供了在同―程序内共享内存地址空间运行的―组线程,线程机制支持并发程序设计技术。
2、不同系统中线程机制的比较:
3.4.1 创建线程
1、线程的创建在调用clone()时需要传递一些参数标志来指明所需要共享的资源。
2、clone()参数标志决定新创建进程的行为方式和父子进程之间共享的资源种类。
3.4.2 内核线程
1、内核线程——独立运行在内核空间的标准进程。
2、内核线程和普通的进程间的区别在于内核线程没有独立的地址空间。
3、在Linux系统上运行ps -ef命令,你可以看到内核线程。
4、内核是通过从kthreadd内核进程中衍生出所有新的内核线程来自动处理这一点的,在<linux/kthreadd>中申明有接口。
5、内核退出机制:
3.5 进程终结
1、进程的析构是自身引起的。
2、进程终结会调用do_ exit函数,该函数永不返回。
3、僵死进程存在的唯一目的就是向它的父进程提供信息。
3.5.1 删除进程描述符
1、在linux系统中,进程终结时所需要的清理工作和进程描述符的删除被分开执行。
2、调用release_task函数——最终释放进程描述符。
3.5.2 孤儿进程造成的进退维谷
1、如果父进程在子进程之前退出,必须有机制来保证子进程能找到一个新的父亲,否则这些成为孤儿的进程就会在退出时永远处于僵死状态。
2、解决方法是给子进程在当前线程组内找一个线程作为父亲,如果不行,就让init做它们的父进程。在doexit()中会调用exitnotify(),该函数会调用forgetoriginalparent(),而后者会调用findnewreaper()来执行寻父。
小结
本章的主要内容——进程
问题
1、什么是slab分配器?
2、什么是析构?
参考资料
1、slab百度百科
2、析构函数百度百科
3、《Linux内核设计与实现》第三章