Linux内核学习笔记:进程
进程是多道程序设计的操作系统的基本概念。进程是程序运行的实体。他是描述程序已经执行到了何种程度的数据结构的汇集,也是操作系统分配系统资源(cpu时间,内存,磁盘)的实例。
一. 进程描述符
进程是比较抽象的概念,linux下描述进程的数据结构为进程描述符。进程描述符代表了一个进程所有的数据结构,文件,以及运行上下文。进程描述符是这么的复杂,在linux中大约占用1.7K个字节,完全读懂他还是有一定难度的。但是总的划分为几部分:
(1)thread_info 指针,指像进程的基本信息,这个结构非常重要,他与进程的内核栈存放在一起。一般占用8K个字节,两个页。这个结构体里包含如进程的状态,内核抢占标志,本地CPU号等一些重要的信息。
(2)mm_struct 指针,指向内存描述符指针,内存描述符描述了进程的基本内存信息,包括内存地址空间等。
(3)tty_struct 与进程相关的tty
(4)fs_struct 当前目录
(5)files_struct 指向文件描述符的指针
(6)signal_struct 所接收的信号
thread_info 数据结构描述了进程基本信息,又叫线程描述符。他与进程的内核态栈存放在一起,一般占用8K的内存空间,他的首地址是8K的整数倍。所以只要或得了内核栈指针就可以方便的找到当前进程的线程描述符。从而找到当前进程的进程描述符。current宏就是通过进程的内核栈来找到当前进程的进程描述符。
linux下所有的进程描述符都链接在以init_task进程为首的进程双向链表中,可运行进程还链接在可运行链表中,等待进程链接在不同的等待队列中。这样方便管理。
二. 进程的状态
进程像一个生命一样经历着生老病死。所以进程的状态包括了这个过程。进程包括了七种状态:可运行状态,可中断的等待状态,不可中断的等待状态,暂停状态,跟踪状态,僵死状态,僵死撤销状态。
(1) 可运行状态,进程从建立之初起就是本着运行去的,所以可运行状态是进程的最好的状态,当然可运行不代表这就一定在运行,这种状态代表进程随时准备运行,在CPU的可运行队列里
(2) 可中断的等待状态,进程因为等待一些资源或者磁盘IO而不具备运行的条件。这中状态叫进程的等待状态,可中断的等待状态是,进程可以对信号进行相应而结束等待状态。而不可中断等待状态与其相反。
(3) 暂停状态,进程也不能运行,这种状态是进程收到了一些暂停的信号造成的。
(4) 跟踪状态,一个进程可以跟踪另外一个进程的运行,当跟踪发生时,他就处于跟踪状态。
(5) 僵死状态,进程已经退出,释放了所有的资源,不能够再运行了。但是进程描述符还没有被回收,这时进程处于僵死的状态。
(6) 僵死退出状态,父进程对僵死的进程发出wait4系统调用,回收了进程的描述符,进程就彻底死亡了。
三 标识一个进程与进程关系
linux采用进程标识符来标识一个进程,就是一种编码。linux下进程标识符的上限为32767,用pidmap_array位图来表示当前已经分配的PID号和闲置的PID号。每使用一个进程,linux就在这个位图中空闲位置1来表示进程号已用。进程之间是有关系的,每一个进程都有父进程,然后从属于一个父继承的进程还是兄弟进程,进程描述符中有专门的域来表示进程的这种关系。
四. 由PID到进程描述符
在一些情况下,内核必须由PID导出进程描述符的指针。例如,利用KILL系统调用时。这时必须建立起PID与进程描述符的关系。为了提高效率,linux建立了四个散列表来表示这种映射关系。,之所以采用散列表的原因是linux上限进程数量为32768项,但是系统实际的进程数量却远远少于这个数值,所以如果建立32768个表项的话是一种资源的浪费,所以通过散列表的方式来达到空间的节省。但是散列表不能避免冲突,这里采用链表的方式避免冲突。