linux系统下进程的创建

进程的创建过程:

此处假设linux系统内存为4G空间。

进程创建前,为一个存储在硬盘的程序,此时的程序拥有4G的虚拟内存,并且有1G空间直接被系统内核所占用,余下3G虚拟内存被系统程序分配。

由高至低

系统内核此处占用1G空间
剩下3G空间被合理分配
最上为栈空间(由上至下分配空间)
其次是堆空间(由下至上分配空间)
-------------------------------------------------------------
接下来的空间由一些变量空间和代码段所占用
.bss
.data
.rodata
.text(代码段)
.init(启动部分)
此图是虚拟内存中的大致分布。

程序在终端运行的时候,在内存运行的终端程序bash会将自身复制一份出来,并且同样的在内存中运行。

复制完成之后,会根据将要在内存中运行的程序在虚拟内存中的数据分配,重新的将bash副本中的数据改写,变成即将运行的新的进程。

所以在linux系统运行的进程会有一个父进程,其意思即为从一个进程中复制得出的新的进程。


程序中创建子进程fork函数

在程序运行过程中使用fork函数,系统会自动的创建一个与该函数同名的子进程。

父进程子进程


数据段


数据段
int main(void)
{
  ...
  fork();
  ...
}
fork返回子进程的ID号
与父进程共用
代码段




fork返回的值为0


=================================华丽分割线==================================

2017.1.3补充

对fork函数创建子进程,其代码段共享以及COW(Copy On Write)写时复制技术的理解加深

码了一段代码想看看fork函数出来的所有子进程其对应的Id号,以及其父进程ID号还有组ID号

具体如下

#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
	pid_t id = fork();
	pid_t id2,id1; 
	if(id<0)
	{
		printf("fork failed:%s",strerror(errno));
		return -1;
	}
	else if(id == 0)
	{
		if(setpgrp()==-1)//It is set the id of itself as the new groupid
			printf("set group id is failed:%s",strerror(errno));
		printf("I'm a child p[%d],ppid[%d],pgid[%d]\n",getpid(),getppid(),getpgrp());
	}
	else
	{	
		printf("I'm father p[%d],ppid[%d],pgid[%d]\n",getpid(),getppid(),getpgrp());
		id1 = fork();
		if(id1<0)
		{
			printf("fork failed:%s",strerror(errno));
			return -2;
		}
		else if(id1 == 0)
		{
			printf("I'm the second child p[%d],ppid[%d],pgid[%d]\n",getpid(),getppid(),getpgrp());
			id2 = fork();
			if(id2<0)
			{
				printf("fork failed:%s",strerror(errno));
			}
			else if(id2 == 0)
			{
				printf("I'm the groundchild p[%d],ppid[%d],pgid[%d]\n",getpid(),getppid(),getpgrp());
			}
		}
	}

	sleep(1);
	return 0;

}

这是一个主进程创建两个子进程分别为child1,child2。然后在child2中再次fork创建一个孙子进程。

每个进程都打印出各自的id号,pid号,gid号。分别对应本身id,父进程id,组进程id。

正常的结果应该是先输出父进程,然后child1进程,child2进程,groundchild进程

但是最后的运行结果却是

I'm father p[13564],ppid[11337],pgid[13564]
I'm the second child p[13566],ppid[13564],pgid[13564]
I'm a child p[13565],ppid[13564],pgid[13564]
I'm the groundchild p[13567],ppid[13566],pgid[13564]

我一开始以为是不分先后,可能是后面的执行了,多运行几次可能就会出现不同的结果。

但是不论我怎么运行结果还是这个。

如果second child先输出结果,就是说child2进程要比child1进程要快。

后来经过各种测试,发现原来是因为fork的时间与printf的时间相差不同。

突然想起cow写时复制技术,这个技术是用在fork进程的时候,子进程与父进程共用同一段代码,所有的变量都暂时不复制,当需要为该变量赋值的时候则将变量复制到子进程的栈空间中。

child1是在id定义的时候就已经fork出来,经过了变量的声明,而child2是在父进程判断之后被fork出来,其开始时间比child1晚。

child2不需要写入变量,则不需要将父进程的变量复制一份出来,减去了复制的时间。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值