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

Linux 多進程開發(二):vfork 詳解——地址空間共享與調度特性實戰驗證

     編輯:關於C語言

承接上篇 fork() 創建進程,本文深入講解 vfork() 的獨特機制:地址空間共享、子進程優先調度、修改父進程數據可見性,並通過對比實驗驗證核心差異。

一、 vfork() vs fork() 核心差異

特性fork()vfork()
調用返回一次調用,兩次返回一次調用,兩次返回
資源複製完全複製父進程資源(寫時複製 COW)不複製,子進程共享父進程地址空間
數據隔離子父進程數據互不影響子進程修改直接影響父進程
調度順序不確定,由調度器決定保證子進程先運行,直到 exec 或 exit
死鎖風險無子進程依賴父進程行為時極易死鎖

二、 實驗代碼:並發驗證數據共享與調度

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

int globVar = 5;

int main(void) {
    pid_t pid;
    int var = 1, i;
    printf("fork vs vfork demonstration\n");
    
    // pid = fork();      // 實驗1:取消註釋測試 fork
    pid = vfork();       // 實驗2:取消註釋測試 vfork
    
    switch(pid) {
        case 0:  // 子進程
            i = 3;
            while(i-- > 0) {
                printf("Child process is running\n");
                globVar++; var++;
                sleep(1);
            }
            printf("Child's globVar = %d, var = %d\n", globVar, var);
            _exit(0);  // vfork 必須用 _exit,避免刷新父進程緩衝區
        case -1:
            perror("Process creation failed");
            exit(1);
        default: // 父進程
            i = 5;
            while(i-- > 0) {
                printf("Parent process is running\n");
                globVar++; var++;
                sleep(1);
            }
            printf("Parent's globVar = %d, var = %d\n", globVar, var);
            exit(0);
    }
}

三、 實驗結果對比分析

1. fork() 運行結果

fork 運行結果

分析:

  • 子進程獨立遞增 3 次:globVar=8, var=4
  • 父進程獨立遞增 5 次:globVar=10, var=6
  • 全局/局部變量修改互不影響,證明獨立地址空間
  • 父子進程交替運行,順序不確定

2. vfork() 運行結果

vfork 運行結果

分析:

  • 子進程先運行(遞增 3 次),父進程阻塞等待
  • 子進程 _exit 後父進程繼續遞增 5 次
  • 最終父進程:globVar=13, var=9(5+3+5)
  • 子進程修改直接可見於父進程,證明地址空間共享
  • ps 查看父進程狀態為 S(可中斷睡眠/阻塞)

四、 關鍵注意事項(必讀)

  1. 嚴禁在 vfork 子進程中修改共享變量:除非極其確定,否則會導致父進程數據錯亂
  2. 子進程必須調用 _exit() 而非 exit():exit() 會刷新 stdio 緩衝區,破壞父進程緩衝區狀態
  3. 不要在子進程中調用非 async-signal-safe 函數:包括 malloc、printf、鎖操作等,極易死鎖
  4. 僅用於緊接 exec() 的場景:現代 Linux fork() 已優化(COW),性能差異微乎其微,vfork() 除非極度敏感場景不推薦常規使用
  5. POSIX 標準已標記 vfork 為「過時」:新代碼優先使用 posix_spawn() 或帶 clone() 參數的 fork()

五、 進程狀態補充

  • S:可中斷睡眠(等待事件)
  • D:不可中斷睡眠(通常為 I/O)
  • 可通過 ps -eo pid,ppid,stat,cmd 觀察父進程阻塞狀態

本文出自 “_Liang_Happy_Life__Dream” 博客,轉載請保留出處:原文鏈接

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved