1. 程式人生 > >作業系統-關於fork&父程序&子程序

作業系統-關於fork&父程序&子程序

前言

這學期在學作業系統,目前感覺還是挺有意思的。

作業系統老師:“鼓勵你們大開腦洞多試試,會有各種奇異的結果,但是最後居然都能解釋出來。”

本文是根據課上講解+自行實踐寫的。

測試環境:Ubuntu

正文

關於fork()的3種返回值

  • 這裡提到的fork和下面程式中使用的fork()是一個C語言庫函式,不是系統呼叫級別的fork();它根據不同的情況會返回3種類型的值。(而系統呼叫級別的fork只返回一種值:那就是創建出來的子程序的pid。)
    1. 在父程序中,返回建立的子程序的pid
    2. 在子程序中,返回0
    3. 出錯,返回負值

下面程式的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’。

  • 輸出結果:
    1. 第一種:
      start…parent process
      start…child process
    2. 第二種:
      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(),無法執行下面的語句,造成從表面上看好像沒有執行的假象。