当前位置:   article > 正文

学习笔记——fork()函数和vfork()函数详解_fork()是什么函数

fork()是什么函数

先来认识认识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;
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

打印结果如下:

pid is 7964
pid is 7964
  • 1
  • 2

我们可以看到,通过执行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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

定义一个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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

接下来看看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;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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

before fork pid :8356
father pid is 8356
child pid is 8357
  • 1
  • 2
  • 3

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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

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

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

  • 1
  • 2
  • 3
  • 4

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

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

下面看看这个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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

使用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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/210644
推荐阅读
相关标签
  

闽ICP备14008679号