Linux fork函數詳細圖解-同時分析一道騰訊筆試題


原創blog,轉載請注明出處

頭文件:

#include<unistd.h>
#include<sys/types.h>
函數原型:
pid_t fork( void);
(pid_t 是一個宏定義,其實質是int 被定義在#include<sys/types.h>中)
返回值: 若成功調用一次則返回兩個值,子進程返回0,父進程返回子進程ID;否則,出錯返回-1
注意,子進程是父進程的副本,拷貝父進程的數據空間,堆棧等資源。父子進程不共享上述資源。
每執行一次fork()函數,會返回兩次,一次是在父進程,一次是在子進程,兩次的返回值不一樣。

我們來看一個簡單的例子

#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char ** argv )
{
pid_t result = fork();
if(result < 0)
{
printf("Error");
}
else if(result == 0)
{
printf("From the son");
}
else
{
printf("From the father");
}
}

輸出

From the son
From the father

可以看到,父子進程都同時執行了這段代碼。可以這么理解,子進程拷貝父進程的所有代碼,和堆棧,然后從fork()的下一行,子進程執行

再看一個例子

代碼

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char ** argv )
{
int i;
for(i = 0;i < 2;i++)
{
fork();
printf("%d\n",i);
}
}


然后我們編譯執行
執行的結果是
[root@localhost test]# gcc -o first first.c 
[root@localhost test]# ./first
0
1
1
0
1
1


為了便於分析,我們每次都輸出當前進程的ppid(父進程)以及當前進程的pid

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char ** argv )
{
int i;
for(i = 0;i < 2;i++)
{
fork();
printf("%d PPID:%d PID:%d\n",i,getppid(),getpid());
}
}

結果

[root@localhost test]# ./first
0 PPID:4984 PID:4985
1 PPID:4985 PID:4986
1 PPID:4984 PID:4985
0 PPID:4424 PID:4984
1 PPID:4984 PID:4987
1 PPID:4424 PID:4984
先分析PID,一共有4種,所以一共有4984,4985,4986,4987四個進程,所以4424是最開始的進程(main)的父進程,所以,最開始的進程是4984
然后依據pid來梳理進程的父子關系
按照子進程->父進程
4986->4985->4984->4424
4987->4984->4424

所以按照這個關系,我們畫圖來分析比較直觀

其中,輸出的順序按照紅色圈中順序來輸出

由圖可以看出,在我的這個CentOS系統中,子進程比父進程先執行,執行順序在不同系統中不一樣,所以編程的時候應當不依賴執行某一個系統的順序

然后,我們來分析一道經典的筆試面試題

     for(i = 0;i < 2;i++)
{
fork();
printf("%d\n",i);
}
}

  for(i = 0;i < 2;i++)
{
fork();
printf("%d",i);
}
}

各輸出了幾個0,幾個1

對於前者

輸出是

0
1
1
0
1
1

對於后者

輸出是

01010101
對於前者,在上面已經進行了圖解,所以不難理解,對於后者,不少同學會很奇怪,為什么輸出了4個0,4個1?

原因是:C語言中,printf函數如果遇到\n,會立即輸出緩沖區內所有內容,如果沒有\n,會先輸出到緩沖區內,等待輸出

我們繼續畫圖來分析,



這里在詳細解釋下:可以這么理解,每次printf的時候,是把本進程的printf緩沖區,加入到總的printf緩沖區(這種說法可能不嚴謹),比如到紅色圈圈3的時候,4985本身在紅色圈圈1的時候緩沖區已經有0了,那么再加入1,則本身進程的緩沖區為01,那么加入到printf總的緩沖區就是0101

原創blog,轉載請注明出處




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com