2.fork创建子进程:vfork

getpid/getppid

getpid  获取当前进程id
getppid 获取当前进程的父进程的id

fork

pid_t fork()
1.为什么fork有两个返回值?
	因为这两个返回值是由不同的进程return出来的,而不是由一个fork函数返回两个数。
(fork后,进程由一个变成两个,两个进程分别有一个返回值)
返回值:
	<0:失败
	>0:当前进程为父进程(父进程的返回值)
	=0:当前进程为子进程(子进程的返回值)
2.子进程创建成功后,代码的执行的开始位置?
	fork代码段的位置
3.父子进程的执行顺序?
	不一定谁先谁后(看谁抢到CPU资源)
4.如何区分父子进程?
	通过fork的返回值

案例1

#include <stdio.h>                                                                                                               
#include <stdlib.h>                                                                                                              
#include <unistd.h>                                                                                                              
#include <sys/stat.h>                                                                                                            
#include <sys/types.h>                                                                                                                                                                                                                                 
int main(){                                                                                                                                                                                                                                        
  for(int i=0;i<4;i++)   //仅仅在父进程中执行一次                                                                                             
    printf("---------%d\n",i);                                                                                                   
                                                                                                                                 
  pid_t pid=fork();                                                                                                              
  if(pid<0){                                                                                                                     
    perror("fork fail");                                                                                                         
  }                                                                                                                              
  if(pid>0){ //parent process                                                                                                    
    printf("parent process,pid=%d\n",getpid());                                                                                  
  }                                                                                                                              
                                                                                                                                 
  if(pid==0){  //child process                                                                                                   
   printf("child process,pid=%d\n",getpid());                                                                                    
  }                                                                                                                              
                                                                                                                                 
 for(int i=0;i<4;i++) //在父进程和子进程中各执行一次                                                              
   printf("%d\n",i);                                                                                                             
}
[gjw@localhost 1-fork]$ gcc fork.c -o fork --std=c99  #编译代码
[gjw@localhost 1-fork]$ ./fork     #执行结果
---------0
---------1
---------2
---------3
parent process,pid=117802
0
1
2
3
child process,pid=117803
0
1
2
3

案例2:循环创建number个子进程

					父进程
子进程1	子进程2	子进程3	......	子进程number				
#include <stdio.h>                                                                                                               
#include <stdlib.h>                                                                                                              
#include <unistd.h>                                                                                                              
#include <sys/stat.h>                                                                                                            
#include <sys/types.h>                                                                                                           
int main(){                                                                                                                      
  int i;                                                                                                                       
  int number=5;                                                                                                                  
                                                                                                                                 
  pid_t pid;                                                                                                                     
  for(i=0;i<number;i++){                                                                                                         
    pid=fork();                                                                                                                  
    if(pid<0){                                                                                                                   
      perror("fork fail");                                                                                                       
      exit(1);                                                                                                                   
    }                                                                                                                            
    if(pid==0)                                                                                                                   
      break;                                                                                                                     
  }                                                                                                                              
                                                                                                                                 
  for(int j=0;j<number;j++){    //判断子进程是第几个孩子                                                                                                 
    if(j==i)                                                                                                                     
      printf("%d process,pid=%d\n",j,getpid());                                                                                  
  }                                                                                                                              
  if(i==number) //判断父进程是哪一个:(父进程退出for循环时,i==number)
    printf("parent process,pid=%d\n",getpid());                                                                                                                                                                                                      
}  
[gjw@localhost 1-fork]$ ./fork 
0 process,pid=70113
1 process,pid=70114
2 process,pid=70115
parent process,pid=70112
4 process,pid=70117
3 process,pid=70116

写时拷贝原则write-on-copy

1.读时共享
	刚fork出来之后,两个地址空间用户区数据完全相同,父子进程都指向同一块共享区域,父子进程中
都映射到共享区域中的变量(int num)
2.写时拷贝
	当后续父子进程对共享区域中的变量进行不同的操作时(父进程对num++,子进程对num--),
	===>发生写时拷贝原则,父子进程各自拷贝出来int大小的空间存放自己的num,因此父子进程
中的num是相互独立,互不影响的====>因此父子进程之间不能够使用全局变量进行通信。

在这里插入图片描述

vfork

  vfork() 函数和 fork() 函数一样都是在已有的进程中创建一个新的进程,但它们创建的子
进程是有区别的。
(1)父子进程的执行顺序
	fork(): 父子进程的执行次序不确定。
	vfork():保证子进程先运行,在它调用 exec/exit之后,父进程才执行
(2)是否拷贝父进程的地址空间
	fork(): 子进程拷贝父进程的地址空间,子进程是父进程的一个复制品。
	vfork():子进程共享父进程的地址空间
(3)调用vfork函数,是为了执行exec函数;如果子进程没有调用 exec/exit, 程序会出错

vfork案例

验证1:vfork父子进程执行顺序
	子进程先执行完exec或exit后
	父进程才开始执行
int main(int argc, char *argv[]){
	pid_t pid;
	pid = vfork();	// 创建进程
	if(pid < 0){ // 出错
		perror("vfork");
	}
	if(0 == pid){  
		sleep(3); // 延时 3 秒
		printf("i am son\n");
		
		_exit(0); // 退出子进程,必须
	}
	else if(pid > 0){ // 父进程
		printf("i am father\n");
	}
}
执行结果:已经让子进程延时 3 s,结果还是子进程运行结束后,父进程才执行

验证2:vfork后,父子进程共享内存空间
int a = 10;
int main(int argc, char *argv[]){
	pid_t pid;
	int b = 20;
	pid = vfork();	// 创建进程
	if(pid < 0){ // 出错
		perror("vfork");
	}
	if(0 == pid){ // 子进程
		a = 100, b = 200;
		printf("son: a = %d, b = %d\n", a, b);
		_exit(0);  
	}
	else if(pid > 0){ 
		printf("father: a = %d, b = %d\n", a, b);	
	}
}
执行结果:子进程先执行,修改完a,b的值后,由于父子进程共享内存空间,因此会影响父进程
	son: a = 100, b = 200
	son: a = 100, b = 200

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/83041030