深入解析Linux進程創建與fork機制

目錄

一、fork函數初識

二、fork函數返回值

思考:

1. fork函數為何給子進程返回0,而給父進程返回子進程的PID?

2. 關于fork函數為何有兩個返回值這個問題

三、寫時復制機制

寫時拷貝(Copy-On-Write)機制解析

1. 必要性:為什么需要寫時拷貝?

2. 延遲拷貝的優勢:為何不立即拷貝?

3. 代碼段的寫時拷貝適用性

關鍵結論

四、fork函數的常規用法

五、fork調用失敗的原因:


一、fork函數初識

????????在Linux系統中,fork函數是一個關鍵的系統調用,它通過復制現有進程來創建新進程。被創建的進程稱為子進程,而原始進程則稱為父進程。

#include <unistd.h>
pid_t fork(void);

函數返回值:

  • 子進程返回0
  • 父進程返回子進程的PID
  • 出錯時返回-1

當進程調用fork函數時,內核會執行以下操作:

  1. 為子進程分配新的內存空間和內核數據結構
  2. 將父進程的部分數據結構內容復制到子進程
  3. 將子進程添加到系統進程列表
  4. fork函數返回,由調度器開始進行進程調度

????????當進程調用fork()后,會生成兩個二進制代碼完全相同的子進程。這兩個進程會從相同的執行點繼續運行,但隨后各自進入獨立的執行流程。請看以下示例代碼:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>int main(void) 
{pid_t pid;printf("Before: pid is %d\n", getpid());if ((pid = fork()) == -1) {perror("fork()");exit(1);}printf("After: pid is %d, fork return %d\n", getpid(), pid);sleep(1);return 0;
}

運行結果:

????????輸出內容分為三行:一行"Before"和兩行"After"。進程2619首先打印"Before"消息,隨后又打印了一條"After"消息。另一條"After"消息則是由進程2620打印的。值得注意的是,進程2620并未打印"Before"消息。為什么呢?如下圖所示:

????????在fork調用之前,父進程獨立運行;調用之后,父進程和子進程將各自執行。需要注意的是,fork之后哪個進程先執行完畢,完全取決于系統調度器的安排。


二、fork函數返回值

  • 子進程返回0
  • 父進程返回子進程的PID
  • 出錯時返回-1

思考:

1. fork函數為何給子進程返回0,而給父進程返回子進程的PID?

????????這種設計源于進程間的關系特性:一個父進程可以創建多個子進程,但每個子進程只能有一個父進程。對子進程而言,它無需識別父進程;而對父進程來說,必須明確每個子進程的標識。父進程需要獲取子進程的PID才能有效分配和管理任務。

2. 關于fork函數為何有兩個返回值這個問題

當父進程調用fork函數時,系統會執行一系列創建子進程的操作:

  1. 創建子進程的進程控制塊
  2. 建立子進程的進程地址空間
  3. 生成子進程對應的頁表完成這些步驟后,操作系統會將子進程的進程控制塊加入系統進程列表,此時子進程創建完成。

????????換句話說,當fork函數執行return語句時,子進程的創建已經完成。因此,后續的return語句不僅由父進程執行,子進程也會執行同樣的操作,這就解釋了為何fork函數會返回兩個值。


三、寫時復制機制

????????子進程剛創建時,與父進程共享相同的內存數據段和代碼段,兩者的頁表都指向同一塊物理內存區域。只有當父進程或子進程嘗試修改數據時,系統才會執行寫時復制操作,將原始數據復制一份供修改使用。

具體原理如下圖所示:

????????得益于寫時拷貝技術,父子進程得以完全分離,從而確保了進程的獨立性。寫時拷貝是一種延遲申請技術,可以有效提高系統內存的使用效率。

這種在需要進行數據修改時再進行拷貝的技術,稱為寫時拷貝技術。

寫時拷貝(Copy-On-Write)機制解析

1. 必要性:為什么需要寫時拷貝?

  • 進程獨立性要求
    多進程環境下,操作系統需確保各進程資源獨占性。寫時拷貝通過延遲拷貝策略,保證子進程修改數據時才會復制父進程資源,避免進程間數據干擾。

  • 性能優化
    直接拷貝父進程全部數據會帶來顯著開銷(如內存占用、CPU復制時間),而多數情況下子進程可能僅讀取數據或使用部分資源。

2. 延遲拷貝的優勢:為何不立即拷貝?

  • 資源利用率

    • 避免冗余拷貝:子進程可能僅訪問父進程部分數據(如只讀代碼段),立即全量拷貝會導致內存浪費。

    • 按需分配:僅在子進程嘗試修改數據時觸發拷貝,減少無效的內存占用(例如fork()后接exec()的場景無需拷貝父進程數據)。

  • 效率提升
    現代操作系統通過頁表映射共享父進程資源,寫時拷貝將實際拷貝操作推遲到最后一刻,顯著降低進程創建開銷。

3. 代碼段的寫時拷貝適用性

  • 常規情況(90%以上)
    代碼段通常是只讀的,父子進程可共享同一物理內存頁,無需觸發拷貝。

  • 例外場景

    • 進程替換(如exec():新程序加載會覆蓋原代碼段,此時需重新分配內存,本質上仍遵循"修改時拷貝"邏輯。

    • 自修改代碼:極少見情況下程序動態修改代碼段內容,會觸發寫時拷貝機制。

關鍵結論

寫時拷貝通過共享只讀、延遲寫入的策略,在保證進程獨立性的同時,最大化內存和計算資源的利用率,是操作系統優化進程創建的核心機制。


四、fork函數的常規用法

  • 父進程需要復制自身,使父子進程可以執行不同的代碼段。例如,父進程監聽客戶端請求,創建子進程來處理具體請求。
  • 進程需要執行新程序。例如子進程在fork返回后調用exec函數。

五、fork調用失敗的原因:

fork函數創建子進程也可能會失敗,有以下兩種情況:

  1. 系統中有太多的進程,內存空間不足,子進程創建失敗。
  2. 實際用戶的進程數超過了限制,子進程創建失敗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89220.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89220.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89220.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【軟件開發】主流 AI 編碼插件

主流 AI 編碼插件1. GitHub Copilot 支持平臺&#xff1a;VS Code、Neovim、JetBrains 系列、Visual Studio 優點 深度語料庫&#xff1a;基于 OpenAI 的大規模模型訓練&#xff0c;能夠生成高質量、上下文相關的代碼補全。多語言支持&#xff1a;對 Python、JavaScript、TypeS…

實訓十一——網絡通信原理

補充如何解決IPv4地址不足的問題&#xff1f;使用專用的IPv4地址范圍&#xff08;如 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16&#xff09;并通過NAT轉換與外部網絡通信&#xff0c;能有效節約公網IPv4地址。根據RFC 1918的定義&#xff0c;以下是保留的私有IPv4地址范圍&am…

Spring Cloud LoadBalancer 詳解

在分布式系統快速發展的當下&#xff0c;服務間的調用日益頻繁且復雜。如何合理分配請求流量&#xff0c;避免單個服務節點過載&#xff0c;保障系統的穩定性與高效性&#xff0c;成為關鍵問題。負載均衡技術便是解決這一問題的重要手段。Spring Cloud LoadBalancer 作為 Sprin…

Linux內核內存管理相關的配置參數

Linux內核內存管理相關的配置參數&#xff08;主要位于/proc/sys/vm/目錄下&#xff09;&#xff0c;用于調整內存分配、緩存管理、交換機制、OOM&#xff08;內存溢出&#xff09;策略等核心內存行為。以下是對每個參數的詳細解釋&#xff1a; admin_reserve_kbytes block_dum…

Web開發 01

先放一下自己寫的手敲的第一個網站代碼&#xff01;~雖然很簡單但還是有點成就感&#xff01;&#xff01;開心&#x1f60a;<!DOCTYPE html> <html><head><title>Title!</title><link rel "stylesheet"href "style.css"…

Redis 生產實戰 7×24:容量規劃、性能調優、故障演練與成本治理 40 條軍規

&#xff08;一&#xff09;寫在前面&#xff1a;為什么需要“軍規” Redis 在測試環境跑得飛快&#xff0c;一到線上就“莫名其妙”抖動&#xff1b;大促前擴容 3 倍&#xff0c;成本卻翻 5 倍&#xff1b;一次主從切換&#xff0c;緩存雪崩導致下游 DB 被打掛&#xff1b;開發…

【DOCKER】綜合項目 MonitorHub (監控中心)

文章目錄1、項目架構圖1.1 架構組件2、實際實施2.1 安裝docker2.2 編寫dockerfile文件2.2.1 Prometheus2.2.2 node_exporter2.2.3 nginxvts模塊2.2.4 nginx_exporeter 服務發現文件2.2.5 maridb dockerfile文件2.2.6 鏡像總數2.3 具體操作2.3.1 Prometheus組件2.3.2 nginx組件2…

Java List 集合詳解:從基礎到實戰,掌握 Java 列表操作全貌

作為一名 Java 開發工程師&#xff0c;你一定在項目中頻繁使用過 List 集合。它是 Java 集合框架中最常用、最靈活的數據結構之一。無論是從數據庫查詢出的數據&#xff0c;還是前端傳遞的參數列表&#xff0c;List 都是處理這些數據的首選結構。本文將帶你全面掌握&#xff1a…

SGMD辛幾何模態分解 直接替換Excel運行包含頻譜圖相關系數圖 Matlab語言!

SGMD辛幾何模態分解 直接替換Excel運行包含頻譜圖相關系數圖 Matlab語言算法近幾年剛提出&#xff0c;知網還沒幾個人用&#xff0c;你先用&#xff0c;你就是創新&#xff01;算法新穎小眾&#xff0c;用的人很少&#xff0c;包含分解圖、頻譜圖、相關系數圖&#xff0c;效果如…

Oracle數據泵詳解——讓數據遷移像“點外賣”一樣簡單?

?今天我想和大家聊一個數據庫領域的“萬能搬運工”——Oracle數據泵&#xff08;Data Pump&#xff09;?。相信很多人都有過這樣的經歷&#xff1a;業務要上線新系統&#xff0c;得把舊庫的數據搬到新環境&#xff1b;或者領導突然要一份3年前的歷史數據&#xff0c;可不能影…

Leetcode 03 java

爬樓梯算法現在只看明白動態規劃&#xff0c;也沒有很難喲&#xff01;&#xff01;題目70. 爬樓梯假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢&#xff1f;java題解class Solution {public int climbStairs(…

怎么刪除 wps 的右鍵菜單

打開 WPS 點擊 WPS Office 選項卡&#xff0c;點擊右側全局配置》配置和修復工具點擊高級功能定制下的都可以關閉和隱藏點擊確定就可以了。

C++:list

一&#xff0c;list的介紹1&#xff0c;list初步&#xff08;1&#xff09;list是 C 標準模板庫 (STL) 中的一個雙向鏈表容器。它允許在常數時間內進行任意位置的插入和刪除操作&#xff0c;但不支持隨機訪問。&#xff08;2&#xff09;list容器的底層數據結構為帶頭雙向循環鏈…

深入理解Collections.addAll方法

文章目錄深入理解Collections.addAll方法概述方法定義基本用法1. 向List添加元素2. 向Set添加元素3. 添加數組元素與傳統add方法的比較使用傳統add方法使用Collections.addAll性能考慮注意事項實際應用場景與Collection.addAll的區別最佳實踐總結深入理解Collections.addAll方法…

CISP-PTE 練習題(完整一套)

目錄 1、SQL注入 2、文件上傳 3、文件包含 4、代碼審計 5、命令執行 6、端口掃描 7、sql 寫 webshell 8、3389 遠程桌面利用 1、SQL注入 sqllabs-less-24 二次注入 2、文件上傳 沒有對文件后綴進行檢測&#xff0c;但是對文件類型有檢測&#xff0c;需要使用圖片頭繞…

Vue3入門-計算屬性+監聽器

&#x1f3e0;個人主頁&#xff1a;Yui_ &#x1f351;操作環境&#xff1a;vscode\node.js &#x1f680;所屬專欄&#xff1a;Vue3 文章目錄1. 計算屬性1.1 computed函數1.2 計算屬性VS普通函數1.3 計算屬性的完整寫法2. 監聽器3.總結1. 計算屬性 計算屬性&#xff08;compu…

Linux Swap區深度解析:為何禁用?何時需要?

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄前言一、Swap區&#xff1a;Linux的"內存救生圈"二、為什么要禁用Swap&#xff1f;性能的隱形殺手三、何時應該使用Swap&#xff1f;不可或缺的場景四、如…

用TensorFlow進行邏輯回歸(三)

邏輯回歸Logistic regression這個腳本展示如何用TensorFlow求解邏輯回歸。 ()ysigmoid(Axb)我們使用低出生重量數據,特別地:y 0 or 1 low birth weightx demographic and medical history dataimport matplotlib.pyplot as pltimport numpy as npimport tensorflow as tfimp…

mingw 編譯 assimp v6.0.2 解決編譯報錯

mingw 編譯 assimp v6.0.2 理論上看這個就能滿足&#xff1a;在Windows下使用CMakeMinGW64編譯Assimp庫 環境變量問題 i386 architecture of input file CMakeFiles\assimp.dir/objects.a(assimp.rc.obj)’ is incompatible with i386:x86-64 output collect2.exe: error: ld r…

Windows 11清理C盤方法大全:磁盤清理/禁用休眠/系統還原點/優化大師使用教程

Windows 11清理C盤方法1. 使用磁盤清理工具步驟&#xff1a;按 Win S 搜索“磁盤清理”&#xff0c;打開工具。選擇C盤&#xff0c;點擊“確定”。勾選需要清理的文件類型&#xff08;如臨時文件、系統錯誤內存轉儲等&#xff09;&#xff0c;點擊“確定”。確認刪除操作&…