作業系統-關於fork&父程序&子程序
阿新 • • 發佈:2018-12-31
前言
這學期在學作業系統,目前感覺還是挺有意思的。
作業系統老師:“鼓勵你們大開腦洞多試試,會有各種奇異的結果,但是最後居然都能解釋出來。”
本文是根據課上講解+自行實踐寫的。
測試環境:Ubuntu
正文
關於fork()的3種返回值
- 這裡提到的fork和下面程式中使用的fork()是一個C語言庫函式,不是系統呼叫級別的fork();它根據不同的情況會返回3種類型的值。(而系統呼叫級別的fork只返回一種值:那就是創建出來的子程序的pid。)
- 在父程序中,返回建立的子程序的pid
- 在子程序中,返回0
- 出錯,返回負值
下面程式的if分支是對這個知識點的運用。
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid;
pid = fork(); //建立子程序
if(pid==0){
printf("child process\n");
}
else if (pid>0){
printf("parent process\n");
}
else{
//error 這裡不作處理
}
}
輸出結果是:
parent process
child process
(不同作業系統中可能順序不一樣?因為父程序和子程序可以併發,執行順序由作業系統排程策略決定?——不是特別確定)
關於緩衝區
- 上課的時候老師提到了一個例子,讓我們回去自己試試
#include <stdio.h> #include <unistd.h> int main(){ pid_t pid; //第一種 printf("start..."); //第二種 //printf("start...\n"); pid = fork(); if(pid==0){ printf("child process\n"); } else if (pid>0){ printf("parent process\n"); } else{ //error 這裡不作處理 } }
可以看到我們在fork()呼叫前寫了一局printf,兩種情況唯一的區別就是多了個’\n’。
- 輸出結果:
- 第一種:
start…parent process
start…child process - 第二種:
start…
parent process
child process
- 第一種:
看到這個結果我就覺得可能是’\n’能重新整理/清除緩衝區之類的原因吧。然後問了下老師。
- 我:pcb中是否存在類似輸出緩衝區的資訊,而換行可以重新整理/清空緩衝區?所以執行fork()時,"start…"還在緩衝區沒有真正地被輸出在顯示器上,就被複制到子程序的pcb中的緩衝區去了。
- 老師:如果不強制清除緩衝區,想當於子程序不僅copy了父程序的記憶體、PCB,還copy了緩衝區的內容。\n 或者flush都是強制清除緩衝區,所以加\n就是清除之後再執行下一條指令。如果不加\n,提交到緩衝區就接著執行下一條指令了。
關於wait()的機制
- 經過測試,Ubuntu下:當父程序呼叫wait()函式時,是從呼叫的那一刻起,CPU就不再執行父程序了,父程序進入waiting(阻塞)狀態,等待合作程序(子程序)的訊息,直到子程序完全結束,父程序才會變成ready(就緒)狀態。
- 因為只在Ubuntu和Mac os上測試了下,在別的系統中還有一種可能(雖然並未找到這樣的系統,因為根本沒有去試):CPU還是會執行父程序,只是每次執行的時候都因為fork()、wait()返回值之類的原因在一直停留在wait(),無法執行下面的語句,造成從表面上看好像沒有執行的假象。