1. 程式人生 > >學習Linux C程式設計之程序控制程式設計

學習Linux C程式設計之程序控制程式設計

建立程序 fork

fork 的定義

在 Linux 中,我們使用 fork 來建立一個子程序

fork 的返回值

fork 函式有些特殊,成功它返回 2 次,失敗返回 -1,利用這個特性可以判斷當前的程序是子程序還是父程序: 
1. 在子程序中返回 0 
2. 在父程序中返回子程序的程序 ID

fork 的寫時複製技術

通過執行 fork,子程序得到父程序的一個副本,例如子程序獲得父程序的資料空間,堆和棧的副本,但是它們並不共享儲存空間,它們只共享程式碼段。但是在現在的系統實現中,並不執行拷貝父程序的副本,作為替代方案,而是使用寫時複製(Copy - On - Write)技術。

寫時複製:在 fork 之後,這些區域由父子程序共享,而且核心將它們的訪問許可權改變為只讀,如果父子程序中的任何一個試圖修改這些區域,核心只為修改區域的那片記憶體製作一個副本給子程序。

不管是哪種技術實現,最後父子程序的資料都是獨立的,不會相互影響

子程序的執行位置

fork 還有一個特點:子程序不是從 main 函式開始執行的,而是從 fork 返回的地方開始

建立程序 vfork

還有一個建立程序的系統呼叫 vfork,它跟 fork 很相似,但是也有幾點不同: 
1. vfork 的目的是建立一個子程序來執行一個程式 
2. vfork 並不復制父程序地址空間,子程序在父程序地址空間中執行

,並阻塞父程序直到子程序返回 
3. vfork 保證子程序先執行 
4. 子程序需要呼叫 exec 或 exit 函式退出,否則會帶來未知結果。

exec

fork 函式裡面最後也是呼叫 exec 等函式來執行程式的

exec 有很多變種函式,例如 execlpexecle,等等,但基本的用法都是差不多的

執行結果就相當與 shell 命令:ps - ef,其他的變種函式可以通過 man exec 來檢視。

程序等待 wait

父程序可以使用 wait 系統呼叫主動等待子程序或者指定程序結束,並獲得子程序的結束資訊

這個系統呼叫的過程如下: 
1. wait 暫停呼叫它的程序直到子程序結束 
2. wait 呼叫成功返回子程序的 PID 
3. wstatus 儲存子程序的返回資訊(正常退出,異常退出,被訊號殺死),以此來知道子程序是如何結束的

大致的流程如下:

F ---fork------> F -------- wait ----> F ------------->
        |                              |
        |                              |
        |                              |
        -------> C -------------exit() -
  • 1
  • 2
  • 3
  • 4
  • 5

如果子程序呼叫 exit 退出,那麼核心將 exit 的退出狀態碼放在 status 中 
如果程序被殺死,核心將訊號序列放在 status 中

實際使用時,wait 提供了相關的巨集來判斷 status 的狀態

程序結束

既然能夠建立程序,那肯定能夠結束程序,在 Linux 中程序退出又分為正常和異常退出,分別來了解了解。

正常退出

有 5 種正常退出程序的方法: 
1. 在 main 內執行 return,等價於呼叫 exit 
2. 呼叫 exit 
3. 呼叫 _exit 或 _Exit 
4. 程序的最後一個執行緒在其啟動例程中執行 return 語句 
5. 程序的最後一個執行緒呼叫 pthread_exit 函式

異常終止

有 3 種異常終止的方法: 
1. 呼叫 abort,產生 SIGABRT 訊號 
2. 當程序接受到某些訊號時 
3. 最後一個執行緒對「取消」請求作出響應

不管是哪種終止情況,我們都可以使用 wait 或者 waitpid 來得到子程序的退出狀態。