Linux Kernel学习005——进程管理(一)
本节引入进程的概念,进程是操作系统中最基本的抽象概念。操作系统内核中设计如何管理进程:创建进程,表示进程,终止进程等。操作系统要给用户程序提供一个运行环境,因此,进程管理就是内核中很重要的一部分结构。
介绍
进程就是进行中的程序,也即处于执行期的程序。进程并不仅仅是一段可执行程序代码,进程还包括当前活动,如:程序计数器(PC)和处理器寄存器的值,进程堆栈段、数据段、堆等等。Linux内核中也把进程称为任务(task)。
内存中的进程可以大致用下图表示。
这里需要强调:程序本身不是进程,只有到一个可执行文件被载入内存时(比如双击执行文件的图标或在命令中输入可执行文件的名称),一个程序才能成为进程。
现代操作系统一般允许单个进程包括多个控制线程的功能,线程(控制线程的简称)是CPU使用的基本单元,它由线程ID、程序计数器、处理器寄存器和栈组成。一个进程的多个线程共享代码段、数据段和其他操作系统资源,比如:打开的文件和信号。
注:Linux系统中的线程实现比较特别,其并不区分线程和进程,线程是一种特殊的进程。
现代操作系统中,进程提供了两种虚拟机制:虚拟处理器和虚拟内存。前者使得进程以为自己在独享处理器,后者使进程以为自己独享系统的内存资源。
在Linux系统中,进程创建一般是通过系统调用fork()进行的,该系统调用通过复制现有进程创建新的进程。调用fork()的进程为父进程,新进程为子进程。当调用结束时,在返回点上,父进程恢复执行,子进程开始执行。
通常,新的进程是要执行新的程序,因此需要使用exec()系统调用创建新的地址空间,并把程序载入其中。
当进程执行完成后,可以通过exit()系统调用退出执行,该系统调用会结束进程并释放其所占用的资源。父进程可以通过wait()系统调用查询子进程是否终结。
进程退出后会进入僵死状态(在父进程调用wait()前,此时称为僵尸进程),直到父进程调用wait()。若父进程退出,而子进程还在进行,那么这些子进程成为孤儿进程。在Linux系统中,孤儿进程由init进程管理。
创建进程
示例(在Linux系统上创建test.c文件,内容如下):
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main() {
pid_t pid;
pid = fork();
if ( pid == 0 ) {
printf( "Child process: PID %d\n", pid);
} else if ( pid < 0 ) {
perror( "fork" );
} else {
printf( "Parent process: PID %d\n", pid);
}
return 0;
}
编译运行:
gcc test.c -o test
./test
# 结果如下:
Parent process: PID 3510
Child process: PID 0