目录
- 一、了解子进程
- 二、创建子进程
- 1.创建子进程
- 2.区分父子进程
- 三、理解子进程
- 四、创建子进程的意义
进程就是运行中的应用程序,如果一个程序较为庞大,我们可以给这个程序创建多个进程,每个进程负责一部分代码的运行。
A进程如果创建了B进程,A进程就是B进程的父进程,B进程就是A进程的子进程。当然,B进程还可以接着创建子进程,创建出的子进程又可以创建子进程…… 但一般我们不会这么做的,因为这样太过复杂,控制起来比较难。
一、了解子进程
简单来说,子进程就是父进程创造的、来帮父进程干活的进程。比如:领导都不亲自干活,干活都是交给下属去做的。父进程就是领导,子进程就是下属。
子进程在创建出来以后,从创建子进程的那行开始,子进程和父进程运行的是一模一样的代码。
如图:有10行代码,父进程运行到第5行的时候创建了一个子进程,子进程创建出来以后,就和父进程运行着相同的代码。
二、创建子进程
1.创建子进程
用专门的函数来创建子进程,常使用 pid_t fork(void) 这个函数来创建一个子进程。但并不是只有这个函数才可以创建子进程,还有其他的函数。
2.区分父子进程
pid_t fork(void)这个函数最终会有一个返回值,返回一个pid_t类型的数据,在返回这个数据之前,子进程就已经创建好了。
所以在返回数据的时候,父进程就已经创建出来子进程了。因此父进程和子进程都有一个该函数的返回值,并且父子进程的返回值不同,这个一定要记住。
对于父进程来说,这个函数的返回值是子进程的pid(pid是大于0的),对于子进程来说,这个函数的返回值是0。如果子进程创建失败,函数的返回值就是小于0的数。
通过父子进程返回值的不同,我们可以区分父子进程,让父子进程进入不同的代码分支执行程序。
可以看一下下面这段代码:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
/*
创建子进程,通过父进程和子进程返回值的不同,使得父进程和子进程执行不同的代码分支
*/
int main(){
//创建子进程
pid_t val=fork();
//判断父子进程
if(val<0){
//返回值小于0,说明子进程创建失败
printf("create error\n");
}else if(val==0){
//返回值等于0,说明进入这里的是子进程
printf("this is son\n");
}else{
//返回值大于0,说明进入这里的是父进程
printf("this is father\n");
}
}
三、理解子进程
1.创建子进程的本质是什么?
创建子进程其实是通过复制父进程来创建子进程。因为进程的信息保存在pcb中,因此创建子进程其实就是复制父进程的pcb中的大部分信息,用这些信息来创建子进程的pcb。这些信息有:内存指针、上下文数据等。
2.复制内存指针的意义是什么?
内存指针指向程序代码在内存中的位置,复制内存指针意味着子进程和父进程运行的代码是一样的。
3.复制上下文的意义是什么?
(1)上下文代表了程序的执行状态:上文是程序已经执行过的指令和数据,下文是将要执行的指令和数据。
(2)子进程复制父进程的上下文数据意味着子进程复制了父进程的运行位置,也就是说,子进程知道父进程创建子进程的时候,父进程运行到哪里了。为了方便,我们把这个位置叫做创建点。
(3)意味着子进程会从创建点开始运行,在创建子进程后,父子进程都会开始运行相同的代码。这一点可以根据上文的图片来理解。
四、创建子进程的意义
(1)父子进程运行的功能相同,在大量任务处理中,子进程可以用来分担压力。因为我们可以通过函数返回值的不同区分父子进程,从而使父子进程进入不同的代码分支。
(2)子进程可以用来做危险的事情,即便崩溃,也不会影响到父进程。因此危险的事情可以让子进程做,父进程负责统筹兼顾。
(3)子进程的作用主要是用在程序替换中,程序替换就是让子进程去运行另一个程序。