linux关于fork的一些简单概念

我们知道在一个进程中,都会存在一个PCB与之对应,我们一般称它为进程描述符(PCB)。PCB是一个结构体,strcut task_struct,它里面有一个变量名pid,这个变量唯一标识一个进程。

那我们在fork一个进程时,实际上就是从内核中申请一个同样大的空间,这个空间的内容大小和被复制的进程是一样。唯一不同的是,指向这两个进程的pid并不是同一个pid。我们习惯称被复制的进程为父进程,复制出来的进程称作子进程
在这里插入图片描述
需要注意的是,父子进程的返回值是不一样的:父进程返回的是子进程的pid,子进程返回的是0。父进程的父进程(ppid)是bash进程,也就是说,父进程也是由它的父进程复制出来的
包含fork方法的头文件是#include <unistd.h>
pid_t fork(void);pid_t的本质是上是int,它是fork返回值的类型。

我们可以先写一个代码来分别打印父子进程的pid,首先fork一个进程,并断言开辟成功。如果pid的值等于0,说明这是一个子进程,打印"this is a child’s id’。如果pid的值不为零,那么就打印出"this is a father’s id"。在这个过程中,子进程会打印三次,父进程会打印7次。
在这里插入图片描述
打印结果如下:
在这里插入图片描述
我们需要注意的是,如果我们将父子进程的地址也做打印的话。我们会发现父子进程的地址居然是一样的。那我们是不是就可以理解为父子进程公用一块内存呢?
这样的观点是错误的,首先我们打印出来的地址是一个逻辑地址(也叫虚拟地址),它并不是我们正真存放内存的物理地址。那我们通过这样一幅图来说明逻辑地址和物理地址的区别。
在这里插入图片描述
在上面的两个页表中,我们可以把它们看成两个进程中数据存放的位置。左边的列是逻辑地址,右边的列是物理地址。在第一行中,虽然它们的逻辑地址都是0,但是它们在物理地址中的映射却是不一样的。所以在一个进程中地址相同时,我们可以说是用了同一块内存。当两个或两个以上的进程拥有同一个逻辑地址时,我们并不认为它们用的是同一块内存地址。

int main()
{![在这里插入图片描述](https://img-blog.csdnimg.cn/20200817144931956.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1X19faGFv,size_16,color_FFFFFF,t_70#pic_center)

	int i=0;
	for(;i<2;i++)
	{
		fork();
		printf("A");
	}
	exit(0);
}

在这个函数中,我们总共会打印出几个A呢?
当i第一次进入父循环此时i的值为1,fork第一个子进程,输出A;第二次i <2 ,i++,fork 第二个子进程打印A。此时父进程循环完毕。
第一个子进程fork出来后直接输出A,此时i=1,第二次进入循环fork第三个子进程,打印A
第二个子进程fork出来时i=2,直接打印A
第四个子进程fork出来时1=2,直接打印A
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值