2.fork建立子程序:vfork
阿新 • • 發佈:2018-11-12
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