学习笔记——fork()函数和vfork()函数详解

先来认识认识fork

fork()函数是创建进程函数。 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

其函数原型为:

pid_t fork( void);
当调用fork()时,将执行以下动作:

向系统申请一个新PID
创建子进程,复制父进程的PCB,获得父进程的数据空间、堆、栈等资源的副本
在父进程中返回子进程的PID,在子进程中返回0
执行完以上动作后,父进程和子进程便开始并发执行了。

需要注意的是:

  1. 程序代码中遇到fork就会创建一个子进程,此时父进程和子进程是共同存在的,一起执行下面的代码
  2. fork函数有三种情况的返回值
    第一种:创建出现错误,返回一个负值
    第二种:创建成功后,在父进程中fork返回新创建子进程的进程ID
    第三种:创建成功后,在子进程中返回0

这也就是说, 在fork函数执行完毕后 ,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

vfork函数在后面


接下来我们通过几个demo来实现看看

demo1:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main(){
	pid_t pid;
	pid =getpid();
	
	fork();
	printf("pid is %d\n",pid);
	
	return 0;
	
}

打印结果如下:

pid is 7964
pid is 7964

我们可以看到,通过执行fork函数,我们得到了两次打印,这个demo分不清楚父进程和子进程,接着看看demo2


demo2:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main(){
	pid_t pid;
	pid_t rpid;
	pid =getpid();
	
	printf("before fork pid :%d\n",pid);
	rpid = fork();
	printf("after fork pid :%d\n ",rpid);
	
	printf("pid is %d\n",getpid());
	
	return 0;
}

定义一个retpid,接收fork的返回值,在fork之前我们看到pid是8188,fork之后pid是8189,也就是在这里创建了一个子进程。通过下面的printf得知,父进程是8188,它返回子进程的pid;fork返回两个值,一个是子进程的id,另一个是0,所以第二次打印after fork pid :0,显示当前子进程的pid是8189。

before fork pid :8188
after fork pid :8189
 pid is 8188
after fork pid :0
 pid is 8189


接下来看看demo3

demo3

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main(){
	pid_t pid;
	pid_t rpid;
	pid =getpid();
	
	printf("before fork pid :%d\n",pid);
	rpid = fork();
//	printf("after fork pid :%d\n ",rpid);
	
	if(pid == getpid()){
		printf("father pid is %d\n",getpid());
	}else{
		
		printf("child pid is %d\n",getpid());
	}
	
	return 0;
}


fork 创建进程后,先执行第一个,如果我的pid和当前getpid一致,就表明此时是父进程在执行操作;如果不一致,也就是子进程在执行,此时的getpid等于rpid

before fork pid :8356
father pid is 8356
child pid is 8357

demo4

通过返回值来判断

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main(){
	pid_t pid;
	pid_t rpid;
	int count = 0;
	
	pid =getpid();
	printf("before fork pid :%d\n",pid);
	rpid = fork();
	
	if(rpid > 0){
		printf("father pid is %d\n",getpid());
		count++;
	}else if(rpid == 0){
		
		printf("child pid is %d\n",getpid());
		count++;
	}else{
		printf("error!\n");
		exit(-1);
	}
	
	return 0;
}

这样很清楚,fork的返回值是childpid和0

before fork pid :8643
father pid is 8643
child pid is 8644


vfork也可以创建进程,与fork有什么区别呢?
区别一:vfork可以直接使用父进程存储空间,不拷贝
区别二:vfork可以保证子进程先运行,当子进程调用exit退出后,父进程才执行

#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t vfork(void);

下面看看这个demo

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main(){
	pid_t pid;
	int count = 0;
	
	pid =getpid();
	pid = vfork();
	
	if(pid > 0){
						
		while(1){
			printf("father pid is %d\n",getpid());
			sleep(1);
		}
	}else{	
		while(1){	
			printf("child pid is %d\n",getpid());
			sleep(1);
			count++;
			if(count == 3){
				exit(0);
			}
		}	
	}		
	return 0;
}

使用vfork函数首先保证子进程执行完,在执行父进程,在代码中,子进程执行三次,父进程才执行。
看看结果:
在这里插入图片描述

而如果把其中的while循环代码换一下,使用fork函数执行,就会发现子进程和父进程交替执行,或者是依据系统调度交替执行

	pid = fork();
	
	if(pid > 0){
						
		while(1){
			printf("father pid is %d\n",getpid());
			sleep(1);
		}
	}else{	
		while(1){	
			printf("child pid is %d\n",getpid());
			sleep(1);
		}	
	}		
	

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

石子君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值