进程(二)—— fork()创建子进程

假设进程A在运行过程中遇到非法请求

但是进程A手里有活,要忙手上的事,所以进程A创建一个子进程a,让子进程a去处理非法请求


目录

一、子进程创建代码实现

1、fork()函数

2、使用fork()函数创建子进程

二、子进程的创建过程

1、创建子进程

2、运行子进程

三、让父子进程执行不同的任务

1、判断父子进程的依据

2、分配任务

3、写时拷贝

4、代码分析


一、子进程创建代码实现

1、fork()函数

fork 函数的作用是创建一个子进程,函数声明如下:

这里提一下返回值,父进程创建成功会返回子进程的PID,创建失败返回 -1,创建出子进程以后,子进程也会执行fork,但是子进程不会继续创建新的进程,因此返回值是0。这是我们辨别父子进程的关键依据。

  • 子进程运行 fork()函数 返回0
  • 父进程运行 fork()函数 返回子进程的PID

2、使用fork()函数创建子进程

函数的具体使用如下, getpid()  可以获取当前进程的PID,返回值是int类型

测试结果如下,我们会发现,printf函数执行了2次,而且打印的内容都不一样,这是因为子进程在被创建出来以后,会继承父进程的一部分代码 (fork函数之后的代码) ,正因为如此,这段代码既会被父进程运行,还被子进程运行

二、子进程的创建过程

1、创建子进程

之前说到,在当前阶段, 进程 = 进程控制块(task_struct) + 进程的代码和数据

进程控制块(task_struct):子进程的task_struct会以父进程的为“模板”,来初始化子进程的

                                              task_struct

进程的代码和数据:默认情况下继承 “父进程” 的代码和数据(实际上是共享

                                假设父进程里有个数据 a = 100,那么父、子进程会指向同一块空间

问:父子进程虽然共享一份代码和数据,但是子进程要修改数据该怎么办??

2、运行子进程

现在子进程也有了,接下来需要做的就是让子进程干活了!

上面说到,父子进程共享一份代码和数据,也就是说下面截图中的代码,父、子进程都会运行

(1) 父进程

 所以结果的第一行会打印  父进程的pid 和 子进程的 pid

(2) 子进程

 打印的顺序不一定是先打印父进程,然后打印子进程,顺序是随机的,子进程被创建以后,会立马加入到运行队列中,谁先运行完,就先打印

三、让父子进程执行不同的任务

创建子进程,难道就是执行和父进程一样的代码?? 肯定不是这样,我们要给子进程分配独有的任务,我们在之前代码的基础上作出修改

1、判断父子进程的依据

父、子进程运行同一份代码,那我们要怎么让子进程做 独有的任务??

父进程 运行fork函数的返回值子进程的pid

子进程 运行fork函数的返回值0

所以我们只需要把 子进程执行的任务放在 if语句中

//id为0代表子进程
if(id == 0)
{
    //子进程的任务
}

2、分配任务

首先,最开始声明一个变量 ret,初始化为100

其次,在子进程修改 ret 的值,改为 20

最后,打印输出结果

我们先看看结果如何??

 我们发现,两次打印的值居然不一样,不是说父子进程共享一份数据和代码吗??

答案是发生了写时拷贝!!

3、写时拷贝

进程之间是相互独立,互不影响的!!

当子进程要修改父进程的数据时,OS会另外开辟一块空间给子进程

所谓写时拷贝,就是在写(修改)数据的时候,把数据另外拷贝一份 

这样的话,子进程修改的数据就不会影响到父进程了

问:为什么不在一开始就开辟空间??

答:如果这份代码无需修改数据,一开始就开辟会浪费很多空间

了解了写时拷贝,我们继续分析代码

我们依然按照之前的分析方法分析,先分析父进程,然后分析子进程

4、代码分析

(1) 父进程

                                                

 

 (2) 子进程

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值