【Linux學習筆記】進程的fork創建 exit終止 wait等待

【Linux學習筆記】進程的fork創建 exit終止 wait等待

🔥個人主頁大白的編程日記

🔥專欄Linux學習筆記


文章目錄

  • 【Linux學習筆記】進程的fork創建 exit終止 wait等待
    • 前言
    • 1.進程創建
      • 1.1 fork函數初識
      • 1.2fork函數返回值
      • 1.3寫時拷貝
      • 1.4 fork常規用法
      • 1.5fork調用失敗的原因
    • 2. 進程終止
      • 2.1進程退出場景
      • 2.2進程常見退出方法
      • 2.2.1退出碼
      • 2.3.2 _exit函數
      • 2.3.3 exit函數
      • 2.3.4 return退出
    • 3. 進程等待
      • 3.1進程等待必要性
      • 3.2進程等待的方法
        • 3.2.1wait方法
        • 3.2.2 waitpid方法
      • 3.2.3 獲取子進程status
      • 3.2.4阻塞與非阻塞等待
    • 后言

前言

哈嘍,各位小伙伴大家好!上期我們講了環境變量今天我們講的是【Linux學習筆記】進程的fork創建 exit終止 wait等待。話不多說,我們進入正題!向大廠沖鋒!
在這里插入圖片描述

1.進程創建

1.1 fork函數初識

在linux中fork函數是非常重要的函數,它從已存在進程中創建一個新進程。新進程為子進程,而原進程為父進程。

 #include <unistd.h>pid_t fork(void);
//返回值:?進程中返回0,?進程返回?進程id,出錯返回-1

進程調用fork,當控制轉移到內核中的fork代碼后,內核做:

  • 分配新的內存塊和內核數據結構給子進程
  • 將父進程部分數據結構內容拷貝至子進程
  • 添加子進程到系統進程列表當中
  • fork返回, 開始調度器調度

當一個進程調用fork之后,就有兩個二進制代碼相同的進程。而且它們都運行到相同的地方。但每個進程都將可以開始它們自己的旅程,看如下程序。

 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;}        
運?結果:
[root@localhost linux]# ./a.outBefore: pid is 43676After:pid is 43676, fork return 43677After:pid is 43677, fork return 0

這里看到了三行輸出,一行before,兩行after。進程43676先打印before消息,然后它有打印after。另一個after消息有43677打印的。注意到進程43677沒有打印before,為什么呢?如下圖所示
在這里插入圖片描述
所以,fork之前父進程獨立執行,fork之后,父子兩個執行流分別執行。注意,fork之后,誰先執行完全由調度器決定。

1.2fork函數返回值

  • 子進程返回0,
  • 父進程返回的是子進程的pid。

1.3寫時拷貝

通常,父子代碼共享,父子再不寫入時,數據也是共享的,當任意一方試圖寫入,便以寫時拷貝的方式各自一份副本。具體見下圖:

因為有寫時拷貝技術的存在,所以父子進程得以徹底分離離!完成了進程獨立性的技術保證!寫時拷貝,是一種延時申請技術,可以提高整機內存的使用率

1.4 fork常規用法

  • 一個父進程希望復制自己,使父子進程同時執行不同的代碼段。例如,父進程等待客戶端請求,生成子進程來處理請求。
  • 一個進程要執行一個不同的程序。例如子進程從fork返回后,調用exec函數。

1.5fork調用失敗的原因

  • 系統中有太多的進程
  • 實際用戶的進程數超過了限制

2. 進程終止

進程終止的本質是釋放系統資源,就是釋放進程申請的相關內核數據結構和對應的數據和代碼。

2.1進程退出場景

  • 代碼運行完畢,結果正確
  • 代碼運行完畢,結果不正確
  • 代碼異常終止

2.2進程常見退出方法

正常終止(可以通過echo$?查看進程退出碼):

  1. 從main返回
  2. 調用exit
  3. _exit

異常退出:

  • ctrl+c,信號終止

2.2.1退出碼

退出碼(退出狀態)可以告訴我們最后一次執行的命令的狀態。在命令結束以后,我們可以知道命令是成功完成的還是以錯誤結束的。其基本思想是,程序返回退出代碼時表示執行成功,沒有問題。代碼1或以外的任何代碼都被視為不成功。

Linux Shell中的主要退出碼:

退出碼解釋
0命令成功執行
1通用錯誤代碼
2命令(或參數)使用不當
126權限被拒絕(或)無法執行
127未找到命令,或 PATH 錯誤
128+n命令被信號從外部終止,或遇到致命錯誤
130通過 Ctrl+C 或 SIGINT 終止(終止代碼 2 或鍵盤中斷)
143通過 SIGTERM 終止(默認終止)
255/*退出碼超過了 0-255 的范圍,因此重新計算(LCTT 譯注:超過 255 后,用退出取模)
  • 退出碼表示命令執行無誤,這是完成命令的理想狀態。

  • 退出碼1我們也可以將其解釋為“不被允許的操作”。例如在沒有sudo權限的情況下

  • 使用yum;再例如除以等操作也會返回錯誤碼,對應的命令為let a=1/0

  • 130(SIGINT^C)和143SIGTERM)等終止信號是非常典型的,它們屬于 128+n信號,其中n代表終止碼。

  • 可以使用strerror函數來獲取退出碼對應的描述。

2.3.2 _exit函數

#include <unistd.h>void _exit(int status);
//參數:status 定義了進程的終?狀態,?進程通過wait來獲取該值
  • 說明:雖然status是int,但是僅有低8位可以被父進程所用。所以_exit(-1)時,在終端執行$?發現返回值是255。

2.3.3 exit函數

#include <unistd.h>void exit(int status);

exit最后也會調用_exit,但在調用_exit之前,還做了其他工作:

  1. 執行用戶通過atexit或on_exit定義的清理函數。
  2. 關閉所有打開的流,所有的緩存數據均被寫入
  3. 調用_exit
 int main(){printf("hello");exit(0);}
運?結果
:[root@localhost linux]# ./a.outhello[root@localhost linux]#int main(){printf("hello");_exit(0);}
運?結果
:[root@localhost linux]# ./a.out[root@localhost linux]# 

2.3.4 return退出

return是一種更常見的退出進程方法。執行returnn等同于執行exit(n),因為調用main
的運行時函數會將main的返回值當做exit的參數。

3. 進程等待

3.1進程等待必要性

  • 之前講過,子進程退出,父進程如果不管不顧,就可能造成‘僵尸進程’的問題,進而造成內存泄漏。
  • 另外,進程一旦變成僵尸狀態,那就刀槍不入,“殺人不眨眼”的kill-9也無能為力,因為誰也沒有辦法殺死一個已經死去的進程。
  • 最后,父進程派給子進程的任務完成的如何,我們需要知道。如,子進程運行完成,結果對還是不對,或者是否正常退出。
  • 父進程通過進程等待的方式,回收子進程資源,獲取子進程退出信息

3.2進程等待的方法

3.2.1wait方法
#include<sys/types.h>#include<sys/wait.h>pid_t wait(int* status);
返回值:成功返回被等待進程pid,失敗返回-1
參數:輸出型參數,獲取?進程退出狀態,不關?則可以設置成為NULL
3.2.2 waitpid方法
pid_t waitpid(pid_t pid, int *status, int options);返回值:
當正常返回的時候waitpid返回收集到的子進程的進程ID;
如果設置了選項WNOHANG,而調用中waitpid發現沒有已退出的子進程可收集,則返回0;
如果調用中出錯,則返回-1,這時errno會被設置成相應的值以指示錯誤所在;參數:
pid:Pid=-1,等待任一個子進程。與wait等效。Pid>0.等待其進程ID與pid相等的子進程。
status:輸出型參數WIFEXITED(status):若為正常終止子進程返回的狀態,則為真。(查看進程是否是正常退出)WEXITSTATUS(status):若WIFEXITED非零,提取子進程退出碼。(查看進程的退出碼)
options:默認為0,表示阻塞等待WNOHANG:若pid指定的子進程沒有結束,則waitpid()函數返回0,不予以等待。若正常結束,則返回該子進程的ID。
  • 如果子進程已經退出,調用wait/waitpid時,wait/waitpid會立即返回,并且釋放資源,獲得子進程退出信息。
  • 如果在任意時刻調用wait/waitpid,子進程存在且正常運行,則進程可能阻塞。
  • 如果不存在該子進程,則立即出錯返回。

3.2.3 獲取子進程status

  • wait和waitpid,都有一個status參數,該參數是一個輸出型參數,由操作系統填充。
  • 如果傳遞NULL,表示不關心子進程的退出狀態信息。
  • 否則,操作系統會根據該參數,將子進程的退出信息反饋給父進程。
  • status不能簡單的當作整形來看待,可以當作位圖來看待,具體細節如下圖(只研究status低16比特位)

、

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main( void )
{pid_t pid;if ( (pid=fork()) == -1 )perror("fork"),exit(1);if ( pid == 0 ){sleep(20);exit(10);} else {int st;int ret = wait(&st);if ( ret > 0 && ( st & 0X7F ) == 0 ){ // 正常退出printf("child exit code:%d\n", (st>>8)&0XFF);} else if( ret > 0 ){ // 異常退出printf("sig code : %d\n", st&0X7F );}}
}
測試結果:
# ./a.out #
等20秒退出
child exit code:10 
# ./a.out #
在其他終端
kill掉
sig code : 9

3.2.4阻塞與非阻塞等待

  • 進程的阻塞等待方式:
int main()
{pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n",__FUNCTION__);return 1;} else if( pid == 0 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);} else{int status = 0;pid_t ret = waitpid(-1, &status, 0); //阻塞式等待,等待5Sprintf("this is test for wait\n");if( WIFEXITED(status) && ret == pid ){printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));}else{printf("wait child failed, return.\n");return 1;}}return 0;
}
運?結果:[root@localhost linux]# ./a.outchild is run, pid is : 45110this is test for waitwait child 5s success, child return code is :1.
  • 進程的非阻塞等待方式:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>typedef void (*handler_t)();  // 函數指針類型
std::vector<handler_t> handlers;  // 函數指針數組void fun_one() {printf("這是一個臨時任務1\n");
}void fun_two() {printf("這是一個臨時任務2\n");
}void Load() {handlers.push_back(fun_one);handlers.push_back(fun_two);
}void handler() {if (handlers.empty())Load();for (auto iter : handlers)iter();
}int main() {pid_t pid;pid = fork();if (pid < 0) {printf("%s fork error\n", __FUNCTION__);return 1;} else if (pid == 0) {  // childprintf("child is run, pid is : %d\n", getpid());sleep(5);exit(1);} else {int status = 0;pid_t ret = 0;do {ret = waitpid(-1, &status, WNOHANG);  // 非阻塞式等待if (ret == 0) {printf("child is running\n");}handler();} while (ret == 0);if ((WIFEXITED(status)) && ret == pid) {printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));} else {printf("wait child failed, return.\n");return 1;}}return 0;
}

后言

這就是進程的fork創建 exit終止 wait等待。大家自己好好消化!今天就分享到這! 感謝各位的耐心垂閱!咱們下期見!拜拜~

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

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

相關文章

鴻蒙應用開發證書考試的一點想法

一、介紹&#xff1a; 直接上圖 二、體驗后的想法&#xff1a; 1.知識點在指南API參考最佳實踐里面找 2.沒有明確說明考試不能查第1點的文檔&#xff0c;但是考試只有1個小時&#xff0c;合理分配時間 3.切屏三次后自動提交要注意&#xff0c;每月3次機會下月又有3次機會&a…

含錫廢水處理的經濟效益

主要體現在成本節約和資源回收兩方面&#xff0c;具體收益因處理工藝、廢水濃度及規模差異而不同。以下結合不同技術路線進行量化分析&#xff1a; 一、直接經濟效益 資源回收收益 金屬錫回收&#xff1a; 若廢水中錫濃度為100 mg/L&#xff0c;日處理量100噸&#xff0c;則每…

Base64編碼原理:二進制數據與文本的轉換技術

&#x1f504; Base64編碼原理&#xff1a;二進制數據與文本的轉換技術 開發者的數據編碼困境 作為開發者&#xff0c;你是否曾遇到這些與Base64相關的挑戰&#xff1a; &#x1f4ca; 需要在JSON中傳輸二進制數據&#xff0c;但不確定如何正確編碼&#x1f5bc;? 想要在HT…

day49—雙指針+貪心—驗證回文串(LeetCode-680)

題目描述 給你一個字符串 s&#xff0c;最多 可以從中刪除一個字符。 請你判斷 s 是否能成為回文字符串&#xff1a;如果能&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 示例 1&#xff1a; 輸入&#xff1a;s "aba" 輸出&#xff1a;true…

Kubernetes(k8s) 集群的快速部署

實驗目的 本實驗旨在通過 Kubeadm 工具快速部署一個 Kubernetes 1.28.2 集群&#xff0c;包含 1 個 Master 節點和 2 個 Worker 節點&#xff0c;并驗證集群的基本功能。實驗涉及以下關鍵步驟&#xff1a; 環境準備&#xff1a;配置主機名、關閉防火墻、禁用 SELinux、設置時區…

7年經驗的Java程序員的技術知識概覽(及分階段學習計劃、資源推薦、職業發展建議)

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 **一、技術棧全景與深度要求****1. 核心Java…

28、.NET 中元數據是什么?

在.NET中&#xff0c;元數據&#xff08;Metadata&#xff09;是描述程序結構和類型信息的二進制數據集合&#xff0c;它是.NET運行時&#xff08;CLR&#xff09;的核心基礎組件之一&#xff0c;用于支持程序加載、類型解析、反射、安全校驗等關鍵功能。以下是其核心特性和作用…

Idea中實用設置和插件

目錄 一、Idea使用插件 1.Fitten Code智能提示 2.MyBatisCodeHelperPro 3.HighlightBracketPair? 4.Rainbow Brackets Lite 5.GitToolBox(存在付費) 6.MavenHelperPro 7.Search In Repository 8.VisualGC(存在付費) 9.vo2dto 10.Key Promoter X 11.CodeGlance…

Linux新手快速入門指南

Linux新手快速入門指南&#xff1a;從零到熟練的簡明路線圖 對于剛接觸Linux的新手而言&#xff0c;這個開源世界既充滿機遇又令人望而生畏。本文將通過系統化的學習路徑和實戰技巧&#xff0c;幫助您快速突破入門難關&#xff0c;掌握Linux核心技能。 一、突破認知誤區&#x…

交叉編譯paho.mqtt.c和paho.mqtt.cpp(MQTT客戶端)

一、參考資料 【MQTT】paho.mqtt.cpp 庫的 介紹、下載、交叉編譯、MQTT客戶端例子源碼-CSDN博客 【MQTT】paho.mqtt.c 庫的“介紹、下載、交叉編譯” 詳解&#xff0c;以及編寫MQTT客戶端例子源碼-CSDN博客 二、準備工作 1. 重要說明 paho.mqtt.cpp與paho.mqtt.c&#xff…

Flink 源碼編譯

打包命令 打包整個項目 mvn clean package -DskipTests -Drat.skiptrue打包單個模塊 mvn clean package -DskipTests -Drat.skiptrue -pl flink-dist如果該模塊依賴其他模塊&#xff0c;可能需要先將其他模塊 install 到本地&#xff0c;如果依賴的模塊的源代碼有修改&#…

【Agent實戰】從0到1開發一個Python 解釋器 MCP SSE Server

寫在前面 想象一個場景:LLM Agent(如 AutoGPT、MetaGPT 或我們自己構建的 Agent)在規劃任務后,決定需要運行一段 Python 代碼來處理數據或調用某個 API。它不能直接在自己的環境中執行(通常不具備這個能力,也不安全),而是需要將這段代碼發送給一個專門的外部服務來執行…

HTML word屬性

介紹 CSS word-spacing 屬性&#xff0c;用于指定段字之間的空間&#xff0c;例如&#xff1a; p {word-spacing:30px; }word-spacing屬性增加或減少字與字之間的空白。 注意&#xff1a; 負值是允許的。 瀏覽器支持 表格中的數字表示支持該屬性的第一個瀏覽器版本號。 屬…

assertEquals()

assertEquals() 是 JUnit 框架中用于進行斷言操作的一個非常常用的方法&#xff0c;其主要目的是驗證兩個值是否相等。如果兩個值不相等&#xff0c;測試就會失敗&#xff0c;JUnit 會給出相應的錯誤信息&#xff0c;提示開發者測試未通過。下面為你詳細介紹&#xff1a; 方法…

Nginx 反向代理,啥是“反向代理“啊,為啥叫“反向“代理?而不叫“正向”代理?它能干哈?

Nginx 反向代理的理解與配置 User 我打包了我的前端vue項目&#xff0c;上傳到服務器&#xff0c;在寶塔面板安裝了nginx服務&#xff0c;配置了文件 nginx.txt .運行了項目。 我想清楚&#xff0c;什么是nginx反向代理&#xff1f;是nginx作為一個中介&#xff1f;中間件來集…

用 Python 打造打籃球字符動畫!控制臺彩色炫酷輸出,抖音搞怪視頻靈感還原

一、引言&#xff1a;從抖音搞怪視頻到 Python 字符動畫的奇妙之旅 刷抖音時刷到一個神級操作 —— 博主用 01 數字矩陣還原了明星打籃球的經典畫面&#xff0c;字符在控制臺隨動作節奏炫彩跳動&#xff0c;瞬間點燃了技術宅的 DNA&#xff01;作為 Python 圖像處理愛好者&…

《逐夢九天:中國航天編年史》

《逐夢九天:中國航天編年史》 新華社酒泉2025年4月24日電(記者李國利、黃一宸)神舟二十號載人飛船發射4月24日取得圓滿成功,中國載人航天在“東方紅一號”發射55載之際開啟第20次神舟問天之旅。 當日17時17分,搭載神舟二十號載人飛船的長征二號F遙二十運載火箭在酒泉衛星…

IDEA搭建環境的五種方式

一、普通的java項目 File--New--Project 選擇Java&#xff0c;jdk選擇1.8版本&#xff0c;然后點next 輸入項目名和路徑名&#xff0c;點擊Finish 創建包結構&#xff0c;編寫Class類 編寫主方法&#xff0c;輸出Hello標志完成 二、普通的javaWeb項目 Java Enterprise-- 勾選…

【黑馬 微服務面試篇】

分布式事務 cap定理-Availability CAP定理-Partition tolerance BASE理論 BASE理論是對CAP的一種解決思路&#xff0c;包含三個思想&#xff1a; BasicallyAvailable&#xff08;基本可用&#xff09;&#xff1a;分布式系統在出現故障時&#xff0c;允許損失部分可用性&#…

實時數倉體系概覽與架構演進

? 引言&#xff1a;為什么我們離不開“實時” 曾經的你可能會認為“數據分析一天一更&#xff0c;夠用了”。但當你所在的公司遇上這些情況&#xff1a; 用戶在投放廣告后5分鐘內就想知道轉化效果 風控平臺必須秒級判斷是否攔截訂單 新產品上線后一小時就需調整推薦算法策略…