linux 进程管理
1.1进程概述
进程就是处于执行期的程序,但进程不仅仅局限于一段可执行代码。通常还包括其他资源(例如打开的文件,内部数据,处理器状态,数据段等等)。
在现代操作系统中,进程提供了两种虚拟机制:虚拟处理器(进程调度)和虚拟内存(虚拟内存管理)。各个线程之间可以共享虚拟内存,但是拥有各自的虚拟处理器。
注:在linux中进程的另一个名字是任务(task)。
1.2进程描述符及任务结构
内核把进程的列表存放在叫做任务队列(task list)的循环链表中。链表中的每一项都是类型为task_sruct的类型,称为进程描述符。它包含了进程的所有信息(例如它打开的文件、进程的地址空间、挂起的信号、进程的状态。。。。)。
1.2.1分配进程描述符
linux通过slab分配器分配task_struct结构这样能达到对象的复用和着色。在2.6以前的内核中,各个进程的task_stuct结构都是放在内核栈的尾端,现在由slab分配task_struct,现在创建新的结构thread_info,定义如下:
struct thread_info{
struct task_struct *task;
struct exec_domain *exec_domain;
u32 flags;
u32 status;
u32 cpu;
。。。。
}
1.2.2进程状态
进程的状态为以下五种状态之一:
- TASK_RUNNING——进程是可执行的:它或者正在执行,或者在运行队列中等待执行。
- TASK_INTERRUPTIBLE——进程正在睡醒,等待某些条件达成,达成后进程的状态设置为运行。
- TASK_UNINTERRUPTIBLE——进程接收到信号也不会投入运行或唤醒。
- _TASK_TRACED——被其他进程跟踪的进程
- _TASK_STOPPED——进程停止执行,进程没有投入运行也不能运行
1.2.3设置当前进程状态
内核经常需要调整某个进程状态。这时最好用set_task_state(task,state)函数:
设置当前进程状态set_current_state(state)。
1.2.4进程上下文
可执行代码是进程的重要组成部分,这些代码一般在用户空间执行。当一个程序执行系统调用或者触发了某个异常,它就陷入内核空间。此时我们称内核代表进程执行并处于进程上下文中(在中断上下文中,系统不代表进程执行,而是执行一个中断处理程序)。在内核退出时,程序恢复在用户空间会继续执行。
异常和系统调用时系统明确定义的接口,只有通过这两个接口才可以进入内核执行。
1.2.6进程家族树
在linux中,所有进程都是PID为1的进程的后代,系统中的每一个进程必有一个父进程,相应的,每个进程也拥有零个或者多个子进程,拥有一个父进程的进程称为兄弟。进程间的关系在进程描述符中描述。每个task_struct 都有一个指向父进程的task_struct,叫做parent指针。还包含一个称为children的子进程链表。
struct task_struct *my_parent=current->parent
1.3进程创建
linux把进程的产生分成两步:fork()和exec(),首先