3.1进程介绍
1、程序和进程
程序是一个普通文件,是机器代码指令和数据的集合,这些指令和数据存储在磁盘上的一个可执行映像中。可以认为进程是运行中的程序,除了包含程序中的所有内容外,还包含一些额外的数据。进程代表程序的执行过程,是一个动态的实体,随着程序中指令的执行而不断地变化。在某个时刻进程的内容被称为进程映像。
进程是由文本段Text、用户数据段和系统数据段共同组成的一个执行环境。
(1)文本段:存放被执行的机器指令。这个段只读,允许系统中正在运行的两个或多个进程之间能够共享这一代码。
(2)用户数据段:存放进程在执行时直接进行操作的所有数据,包括进程使用的全局变量在内。这里包含的信息可以被改变。虽然进程之间可以共享文本段,但是每个进程需要有它自己的专用用户数据段。
(3)系统数据段:存放程序的运行环境。
在Linux系统中使用ps命令来查看当前系统中的进程和进程的一些相关信息。例如ps -e
2、进程的层次结构
在Linux中,通过调用fork系统调用创建一个新的进程。新创建的子进程也能执行fork,所以,有可能形成一棵完整的进程树。注意,每个进程只有一个父进程,但可以有0个、1个、2个或多个子进程。
init 进程是系统中唯一一个没有父进程的进程,它是系统中的第一个进程,其他进程都是由init进程或init进程的子进程产生的。
在Linux系统中用pstree命令来查看系统中进程的树状结构;也可用ps命令来显示进程的树状结构,例如ps -elH
3、进程状态
最基本的进程状态有如下三种:
1、运行态:进程占有CPU,并在CPU上运行。
2、就绪态:进程已经具备运行条件,但由于CPU忙而暂时不能运行。
3、阻塞态:进程因等待某种事件的发生而暂时不能运行(即使CPU空闲,进程也不可运行)。
进程在生命周期内处于且仅处于三种基本状态之一,这三种状态之间有以下4中可能的转换关系。
(1)运行态——>阻塞态:进程发现它不能运行下去时发生这种转换。这是因为进程发生IO请求或等待某件事情。
(2)运行态——>就绪态:在系统认为运行进程占用CPU的时间已经过长,决定让其他进程占用CPU时发生这种转换。由调度程序引起的。调度程序是操作系统的一部分,进程甚至感觉不到它的存在。
(3)就绪态——>运行态:运行进程已经用完分给它的CPU时间,调度程序从处于就绪态的进程中选择一个投入运行。
(4)阻塞态——>就绪态:当一个进程等待的一个外部事件发生时,发生这种转换。如果这时没有其他进程运行,则从就绪态转换为运行态,该进程便开始运行。
4、进程举例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void do_something(long t)
{
int i = 0;
for(i = 0; i < t; i++)
for(i = 0; i < t; i++)
for(i = 0; i < t; i++)
;
}
int main(void)
{
pid_t pid;
// 此时仅有一个进程
printf("PID before fork(): %d\n", getpid());
pid = fork();
// 此时已经有两个进程在同时运行
pid_t npid = getpid();
if(pid < 0)
perror("fork error\n");
else if(pid == 0){ // 表示子进程
while(1){
printf("I am child process, PID is %d\n", npid);
do_something(10000000);
}
}else if(pid > 0){ // 表示父进程
while(1){
printf("I am parent process, PID is %d\n", npid);
do_something(10000000);
}
}
return 0;
}