1. 程式人生 > >2.fork建立子程序:vfork

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);                                                                                                             
}
[
[email protected]
1-fork]$ gcc fork.c -o fork --std=c99 #編譯程式碼 [[email protected] 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());                                                                                                                                                                                                      
}  
[
[email protected]
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