进程:程序执行的基本模型
本章内容
- 程序
- 进程描述符
- 进程的生命周期
- 进程的终止
- 了解进程的动态:调度程序的基本架构
- 等待队列
- 异步执行流程
进程是程序执行的基本单位,是了解操作系统工作原理的重要概念。程序指的是有若干函数组成的可执行文件,而进程指的是特定程序的一个示例。进程是对硬件所提供的资源进程操作的基本单元,也是顺序执行其实例程化程序的基本单元。操作系统根据进程的需要和使用系统资源。
1.1 程序
下述C程序阐明了进程可能经历的各种状态、系统调用以及对支持进程执行的内核对象的操作。其目的是帮助大家理解程序是如何被实例化成进程的,操作系统又是如何处理进程的。
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(int argc, char *argv[]) { int fd; int pid; pid = fork(); if(pid == 0) { execl("/bin/ls",NULL); exit(2); } if(waitpid(pid) < 0) { printf("wait error.\n"); } pid = fork(); if(pid == 0) { fd = open("Chapter_03.txt",O_RDONLY); close(fd); } if(waitpid(pid) < 0) { printf("wait error.\n"); } exit(0); }
1.2 进程描述符
在内核中,进程描述符位一个名为task_struct的结构体,用于存放进程的属性和信息,与进程相关的所有内核信息都存储在这个结构体中,在其生命周期内,进程要与内核的很多方面—如内存管理和进程调度等打交道。因此,进程描述符除了记录UNIX进程的标准属性外。还要记录上述交互过程的相关信息。内核采用循环双向链表task_list来存放所有进程描述符,并借助全局变量current来存放当前运行进程的task_struct的引用。
进程可能有一个或多个线程组成,每个线程都对应一个task_struct,其中包括一个唯一的线程ID。在一般的进程中,线程共享相同的内存地址空间。
以下是在进程的生命周期中,进程描述符必须记录的信息:
- 进程的属性
- 进程间的关系
- 进程的内存空间
- 文件管理
- 信号管理
- 进程的信任状
- 资源限制
- 与调度相关的字段
1.2.1 与进程属性相关的字段
进程的属性分类是我们为进程特征定义的包罗万象的分类,这些特征与进程的状态和标识相关。任何时候检查这些域的值均为内核黑客提供了获取进程当前状态的机会。
1 state
state字段用于记录进程的状态,在其执行生命周期内,进程可以从该域中找到自己所处的状态,其可能的值有TASK_RUNNING,TASK_INTERRUPTIBLE,TASK_UNINTERRUPTIBLE,TASK_ZOMBIE,TASK_STOPPED以及TASK_DEAD。
2 pid
在linux中,每个进程都有唯一的进程标识符pid。pid位于task_struct结构体中,类型为pid_t。
3 标志
标志定义的是进程的特殊属性。每个进程的标志都是在include/linux/sched.h中定义的。下表给出了这些标志的值,他们为内核黑客提供了进程所处状态更多相关信息。
Flag名称 | 何时设置 |
FF_STARTING | 进程创建时设置 |
FF_EXITING | 调用do_exit()时设置 |
FF_DEAD | 进程推出,调用exit_notify()时设置,此时,进程的状态是TASK_SOMBIE或TASK_DEAD |
FF_DORKNOEXEC | 父进程创建子进程是设置该标志 |
4 binfmt
Linux支持多种可执行文件格式。可执行文件格式是为指明程序代码如何被载入内存而定义的一种结构。下图说明了task_struct和linux_binfmt结构体之间的关系。其中,linux_binfmt结构体包含了与特定二进制格式相关的所有信息。
5 exit_code和exit_signal
exit_code与exit_signal字段分别存放进程的退出值和终止信号,这是将紫禁城的退出值传给其父进程的方式。
6 pdeath_signal
pdeath_signal是父进程消亡时发出的信号。
7 comm
通常通过在命令行调用一个可执行程序来创建进程。调用时,comm字段用于存放该可执行程序的名称。
8 ptrace
当进程因进行性能测试而调用系统调用ptrace()时设置ptrace字段。ptrace()的标志在文件include/linux/ptrace.h。
1.2.2 与调度相关的字段
当多个进程都准备号等待运行时,由调度程序决定谁先运行、运行多长时间。调度程序通过给每个进程分配一个时间片和优先级来实现公平,高效的调度。时间片定一个一个进程被切换掉,运行另一个进程之前运行运行的时间长度。进程的优先级则是一个数值,它定义了相对其他就绪进程而言,进程被允许执行的相对顺序。优先级越高的进程会越早被调度运行。
1 prio
进程动态优先级是由进程的调度历史及一个具体的nice值确定的值。当进程时间片用完且进程未被执行时,器动态优先级将在睡眠时被更新。
2 static_pro
static_pro的值等于nice的值,前者的默认值位MAX_PRIO-20.