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

《linux内核设计与实现》--从内核出发 第二章 进程线程

通常进程还要包括其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间以及一个或多个执行线程,当然还包括用来存放全局变量的数据段等。程序本身并不是进程,进程是处于执行期的程序以及相关的资源的总称。

         线程,内核调度的就是线程,而不是进程。每个线程都拥有一个独立的程序计数器、进程栈和一组进程寄存器。内核调度的对象是线程,而不是进程。在传统的UNIX系统中,一个进程只包含一个线程,但现在的系统中,包含多个线程的多线程程序司空见惯。Linux系统的线程实现非常特别:它对线程和进程并不特别区分。对linux而言,线程只不过是一种特殊的进程罢了。                                                                                                                        

《linux内核设计与实现》第二章

进程描述符以及任务结构

         内核把进程的列表存放在叫做任务队列的双向循环链表中。链表中的每一项都是类型为task_structa、称为进程描述符的结构。

         Linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色的目的(以后的内容)。现在都是使用slaba分配器动态生成task_struct,只需在栈底或栈顶创建一个新的结构struct thread_info(这个结构体中包括了struct task_struct)每个任务的thread_info结构在它的内核栈的尾端分配。结构中task域中存放的是指向该任务实际task_struct的指针。

         这里提高进程的五种状态:运行、可中断、不可中断、跟踪、终止。

 

         可执行程序代码时进程的重要组成部分。这些代码从一个可执行文件载入到进程的地址空间执行。一般程序在用户空间执行。当一个程序调用系统调用或者触发了某个异常,它就陷入了内核空间。此时,我们称内核“代表进程执行”并处于进程上下文中。系统调用和异常处理程序对内核明确定义的接口。进程只有通过这些接口才能陷入内核执行—对内核的所有访问都必须通过这些接口。

         Linux通过clone()系统调用来实现fork()。然后由clone()去调用do_fork()。这个函数再调用copy_process()函数,然后让进程开始运行。但是copy_process()函数的所做的工作是很多的。

         在这本书中一直说线程和进程是同一个概念,我个人觉得这只是在这本书中的解释,因为书中并没有提到pthread_create()这个函数,这里一直说线程和进程在linux内核中是不区分的,但是我觉得还是很大的区别的。

         进程在退出后,调用do_exit()之后,线程已经僵死不再运行了,但是系统还保留了它的进程描述符。进程的终结时所需的清理工作和进程描述符的删除被分开执行,在父进程获得已终结的子进程的信息后,或者通知内核它并不关注那些信息后,子进程的task_struct结构才被释放。

 

关于进程的几个重要的结构之间的关系,struct thread_info->struct task_struct