首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

UNIX 系統程式設計筆記(三):進程控制核心概念與系統呼叫實戰

     編輯:關於C語言

進程生命週期總覽

  1. 啟動:int main(int argc, char *argv[]),argv 存放命令列參數,環境變數可用全域 environ 存取。
  2. 運行中:fork() 建立子進程(複製地址空間),vfork() 共享地址空間(極速但危險),exec() 族替換程式映像(PID 不變),system() 執行 Shell 命令(注意 setuid 權限傳遞風險)。
  3. 結束:正常 exit()/return(刷新 I/O 緩衝),異常 _exit()/_Exit()(直接返回核心,不刷緩衝)。

核心系統呼叫與知識點

1. atexit() 註冊結束處理器

採堆疊順序(後進先出)執行:


#include <apue.h>

static void funcA_1() { printf("funcA_1\n"); }
static void funcB_2() { printf("funcB_2\n"); }
static void funcA_3() { printf("funcA_3\n"); }

int main() {
    atexit(funcA_1);
    atexit(funcB_2);
    atexit(funcA_3);
    exit(0);
}
// 輸出順序:funcA_3 → funcB_2 → funcA_1

2. 進程記憶體佈局四區

  • 初始化資料段:全域/靜態且有初值(int a = 1;)。
  • 未初始化資料段 (BSS):全域/靜態無初值,核心自動清零。
  • 堆疊:自動變數、函數呼叫框架、返回位址。
  • 堆積:malloc/free 動態分配。

3. 進程 ID 與關係

  • getpid() 取得自身 PID,getppid() 取得父進程 PID。
  • PID 0:排程器;PID 1:init 進程(所有孤兒進程的最終繼承者)。
  • 父進程先結束 → 子進程成為孤兒 → init 收養(init 會 wait 所有子進程,不產生殭屍)。

4. fork() 與 vfork() 差異

5. wait()/waitpid() 防殭屍


#include <apue.h>

int main() {
    pid_t pid = fork();
    if (pid < 0) err_sys("fork error");
    else if (pid == 0) {  // child
        exit(1);
    }
    sleep(2);  // 父進程故意不 wait
    system("ps -o pid,ppid,state,tty,command");
    exit(0);
}
// ps 輸出會出現  Z 狀態進程 → 殭屍

父進程必須 wait 回收子進程退出狀態,否則子進程進入 Z 狀態佔用 PID 資源。

6. exec() 族函數

  • 成功不返回,失敗返回 -1;原程式 exec 後指令不再執行。
  • execl("./prog", "prog", "arg1", (char*)0):argv[0] 慣例為程式名,易誤用為第一個參數,建議佔位後從 argv[1] 開始使用。

7. system() 安全性陷阱

絕對不要在 setuid/setgid 程式中呼叫 system()!它會啟動 Shell,繼承提升後的權限,導致任意命令執行漏洞。

APUE 精華筆記摘錄

  1. exit() = 清理緩衝 + 關閉標準流 + 返回核心;_exit() 直接返回核心。
  2. return n 在 main 中等同 exit(n)。
  3. 核心唯一透過 exec 族啟動新程式。
  4. 堆疊儲存自動變數與呼叫框架。
  5. 進程只能影響自身及子進程環境,無法影響父進程(通常是 Shell)。
  6. PID 0 為核心排程器,無磁碟映像;PID 1 為 init,擁有超級權限的用戶進程。
  7. fork() 呼叫一次、返回兩次(父/子各一次)。
  8. 子進程獲得父進程資料段、堆積、堆疊的副本,共享程式碼段。
  9. sizeof(array) 回傳整個陣列位元組數(含 \\0);sizeof(ptr) 回傳指標大小;strlen 不含 \\0。
  10. 標準輸出連接終端機時為行緩衝,否則全緩衝。
  11. 所有開啟檔案描述符在 fork 時複製;共享 file table 即共享 current file offset。
  12. 進程終止時核心統一關閉描述符、釋放記憶體。
  13. 異常終止由核心產生退出狀態;核心以 SIGCHLD 通知父進程。
  14. wait() 唯一錯誤為「無子進程」;EINTR 需重試。
  15. fork 建立進程,exec 載入新程式。
  16. ARG_MAX ≥ 4096 bytes(參數+環境變數總長)。
  17. 檔案描述符 close-on-exec 旗標:置位則 exec 時自動關閉。
  18. 唯有超級用戶進程可修改 Real UID。
  19. scanf/printf 在標準流關閉時返回 -1。
  20. UID 0 = root。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性fork()vfork()
地址空間複製(COW)共享
執行順序不確定(race condition)子進程先跑,父進程阻塞至子進程 exec/exit
用途一般建立子進程緊接 exec 時的效能優化