Linux内核入门(六)——进程基础
什么是进程
进程是程序执行时的一个实例。
它类似于人类,被产生,有或长或短的生命,可以产生一个或多个子进程,最终都要死亡。
从内核的角度看,进程就是用来分配系统资源(CPU时间,内存)的实体。
使用进程的好处是:它做到了合理的隔离资源、运行环境,提升资源利用率。
进程的实体结构包含:
- 进程控制块PCB
- 程序段
- 数据段
程序段和数据段很好理解, 进程被创建之时,存储在硬盘上的程序就被放到程序段里,程序运行时所需的变量,以及产生的临时变量都放在数据段。
那么,这个进程控制块,简称PCB的这个东西是用来干嘛的呢?
我们说,进程像人一样,有生有死,那么内核为了便于管理这些进程,就为每个进程创建了一份“档案”,这个档案就是这里的进程控制块
- 进程控制块本质上是一个结构体,用来描述和控制进程。
- 记录进程当前状态和控制进程运行的全部信息。
- PCB是常驻内存的,存放在系统专门开辟的PCB区域中。
创建一个子进程
知道什么是进程后,我们就可以自己用程序创建一个子进程了。
int main(void)
{
pid_t pid;
pid = fork();
if(pid > 0){
for(int i=0;i<5;i++){
printf("parent process %d,\n",i);
usleep(10);
}
}
if(pid == 0){
for(int i=0;i<5;i++){
printf("chlid process %d.\n",i);
usleep(10);
}
}
return 0;
}
程序中,调用fork()函数创建一个子线程,创建完了,我们看不见,摸不着
笑死,根本不知道这个过程发生了什么。
我们运行上面的函数,就已经出现了一个进程,称之为父进程,创建过程是这样的:
如图所示:我们的父进程,即图上的进程A,调用fork函数,系统进入到内核态,duang!内核负责创造一个和进程A一模一样的进程B,区别在于,进程B的pid号不一样。
好,子进程B被创建好了,程序接下来怎么运行呢?
进程B会执行父进程从fork开始的所有程序,两个进程具有各自的数据区和用户堆栈,从fork起,两个进程就各自运行各自的东西了,分家了,子进程一创建出来就分家,父进程A想要直接读取子进程B里面的数据?读不到,没门!(这里涉及到进程间通信的知识,后续会写)
现在,如图所示:父进程A执行完fork函数后,返回子进程的ID号,这个ID号是个正整数,接着继续执行接下来的程序;
而子进程B则会返回0,进程B也会继续执行接下来的程序。
理解了子进程被创建的过程后,我们再来看上面的代码,fork 函数之后,出现两个 if 语句,在父进程中,由于返回的 pid 号是正整数,所以会执行上面一个 if,而子进程 pid 返回值为0,所以会执行下面一个 if 。执行结果如图所示:
至于父子进程哪个先执行,对我们来说是随机的,主要取决于内核的进程调度策略。