【Linux系統編程】—— 深度解析進程等待與終止:系統高效運行的關鍵

文章目錄

  • 進程創建
    • 再次認識fork()函數
    • fork()函數返回值
  • 寫時拷貝
    • fork常規?法以及調用失敗的原因
  • 進程終?
    • 進程終止對應的三種情況
    • 進程常?退出?法
    • _exit函數
    • exit函數
    • return退出
  • 進程等待
    • 進程等待的必要性
    • 進程等待的?法

進程創建

再次認識fork()函數

fork函數初識:在linux中fork函數是?常重要的函數,它從已存在進程中創建?個新進程。新進程為?進程,?原進程為?進程。

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

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

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

在這里插入圖片描述
在這里插入圖片描述
可以看到, 里面創建了一個進程pid3109,這其實就是子進程。
在這里插入圖片描述
當?個進程調?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.out
Before: pid is 43676
After:pid is 43676, fork return 43677
After:pid is 43677, fork return 0

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

fork()函數返回值

  • ?進程返回0,
  • ?進程返回的是?進程的pid。

寫時拷貝

寫時拷貝(Copy-on-write, COW)是一種優化技術,廣泛應用于計算機系統中,特別是在操作系統、虛擬化和內存管理領域。其主要目的是節省內存資源和提高效率。

工作原理:
寫時拷貝的基本思想是,當多個進程共享相同的資源(例如內存或文件)時,如果一個進程對這些資源進行修改,系統并不會立即為該進程創建資源的副本,而是推遲到該進程真正進行修改時,才為它分配一個新的副本。具體步驟如下:

  • 共享資源:多個進程最初可以共享同一塊內存區域或文件(即資源是只讀的)。
  • 標記只讀:系統會將這些共享的資源標記為只讀。
  • 修改時拷貝:當一個進程嘗試修改共享資源時,操作系統會為該進程創建資源的副本,并將其設為可寫。其他進程仍然使用原始資源,而修改的進程則使用新的副本。
  • 繼續共享:如果其他進程繼續只讀訪問原始資源,不會進行拷貝,節省內存和計算資源。
    具體的理解可以看下面這一張圖片:
    在這里插入圖片描述

優點:

  • 節省內存:由于多個進程或線程可以共享同一資源副本,減少了內存的消耗。
  • 提高性能:避免不必要的拷貝操作,只有在修改資源時才進行拷貝,從而提高了效率。
  • 提高數據一致性:寫時拷貝確保在修改數據時不會影響其他進程或線程讀取到的數據,避免了數據沖突。

缺點:

  • 延遲開銷:在第一次修改資源時,系統需要創建資源的副本,這可能帶來一定的性能開銷。
  • 資源消耗:如果多個進程頻繁進行寫操作,系統會進行多次資源拷貝,可能增加資源消耗。

fork常規?法以及調用失敗的原因

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

原因:

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

進程終?

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

進程終止對應的三種情況

  1. 代碼運?完畢,結果正確
  2. 代碼運?完畢,結果不正確
  3. 代碼異常終止

進程常?退出?法

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

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

異常退出:

  • ctrl + c,信號終?

退出碼(退出狀態)可以告訴我們最后?次執?的命令的狀態。在命令結束以后,我們可以知道命令是成功完成的還是以錯誤結束的。其基本思想是,程序返回退出代碼 0 時表?執?成功,沒有問題。

代碼 1 或 0 以外的任何代碼都被視為不成功。

下面是Linuxshell常見的退出碼
在這里插入圖片描述

_exit函數

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

exit函數

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

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

  1. 執???通過 atexit或on_exit定義的清理函數。
  2. 關閉所有打開的流,所有的緩存數據均被寫?
  3. 調?_exit
    在這里插入圖片描述
    示例;
int main()
{
printf("hello");
exit(0);
}int main()
{
printf("hello");
_exit(0);
}

上面的結果分別為:

運?結果:
[root@localhost linux]# ./a.out
hello[root@localhost linux]#
運?結果:
[root@localhost linux]# ./a.out
[root@localhost linux]#

return退出

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

進程等待

進程等待是指在操作系統中,當一個進程無法繼續執行時,它進入一種阻塞狀態,等待某些條件或事件的發生才能恢復執行。等待通常發生在進程需要等待資源(如CPU、內存、I/O設備等)或與其他進程之間的同步和通信。

進程等待的必要性

  • 資源共享與避免沖突:多個進程共享資源時,等待機制確保不會發生沖突,避免競爭條件。

  • 進程同步與通信:確保進程按照正確順序執行,例如生產者和消費者模型。

  • CPU資源管理:避免無謂的CPU占用,讓等待的進程釋放CPU,提高系統效率。

  • 防止死鎖:通過合理設計等待策略,避免多個進程互相等待,進入死鎖狀態。

  • 提升并發性:使系統能夠并發執行多個進程,最大化資源利用。

  • 提高系統穩定性:管理進程優先級,保證重要任務及時執行,確保系統穩定運行。

進程等待的?法

  1. wait?法
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int* status);
返回值:
成功返回被等待進程pid,失敗返回-1。
參數:
輸出型參數,獲取?進程退出狀態,不關?則可以設置成為NULL
  1. 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,?進程存在且正常運?,則進程可能阻塞。
  • 如果不存在該?進程,則?即出錯返回。
    在這里插入圖片描述
  1. 獲取?進程status
  • wait和waitpid,都有?個status參數,該參數是?個輸出型參數,由操作系統填充。
  • 如果傳遞NULL,表?不關??進程的退出狀態信息。
  • 否則,操作系統會根據該參數,將?進程的退出信息反饋給?進程。
  • status不能簡單的當作整形來看待,可以當作位圖來看待,具體細節如下圖(只研究status低16?特位):
    在這里插入圖片描述

進程的阻塞等待?式:

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);//阻塞式等待,等待5S printf("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.out
child is run, pid is : 45110
this is test for wait
wait 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;
}

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

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

相關文章

國產編輯器EverEdit -重復行

1 重復行 1.1 應用場景 在代碼或文本編輯過程中&#xff0c; 經常需要快速復制當前行&#xff0c;比如&#xff0c;給對象的多個屬性進行賦值。傳統的做法是&#xff1a;選中行-> 復制-> 插入新行-> 粘貼&#xff0c;該操作有4個步驟&#xff0c;非常繁瑣。 那有沒…

基于VSCode+CMake+debootstrap搭建Ubuntu交叉編譯開發環境

基于VSCodeCMakedebootstrap搭建Ubuntu交叉編譯開發環境 1 基于debootstrap搭建目標系統環境1.1 安裝必要軟件包1.2 創建sysroot目錄1.3 運行debootstrap1.4 掛載必要的虛擬文件系統1.5 進入目標系統1.6 使用目標系統&#xff08;以安裝zlog為例&#xff09;1.7 清理和退出 2 基…

NiceFish(美人魚)

前端有 3 個版本&#xff1a; 瀏覽器環境移動端環境Electron 環境 服務端有 2 個版本&#xff1a; SpringBoot 版本&#xff08;已實現基于 Apache Shiro 的 RBAC 權限控制&#xff09;SpringCloud 版本 1.主要依賴 名稱版本描述Angular16.2.0Angular 核心庫。PrimeNG16.2…

華為ENSP:STP和鏈路聚合的管理與配置

這里將不再過度闡述STP和鏈路聚合的理論知識&#xff0c;不清楚的同學可以去觀看Cisco文章中的理論知識 理論知識https://blog.csdn.net/2301_76341691/article/details/145166547?fromshareblogdetail&sharetypeblogdetail&sharerId145166547&sharereferPC&…

【PyCharm】連接 Git

【PyCharm】相關鏈接 【PyCharm】連接 Git【PyCharm】連接Jupyter Notebook【PyCharm】快捷鍵使用【PyCharm】遠程連接Linux服務器【PyCharm】設置為中文界面 要在 PyCharm 中連接 Git&#xff0c;確保您的開發環境已經安裝了 Git&#xff0c;并且 PyCharm 能夠訪問它。 以下…

dl學習筆記:(4)簡單神經網絡

&#xff08;1&#xff09;單層正向回歸網絡 bx1x2z100-0.2110-0.05101-0.051110.1 接下來我們用代碼實現這組線性回歸數據 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

三、華為交換機 Hybrid

一、Hybrid功能 Hybrid口既可以連接普通終端的接入鏈路&#xff08;類似于Access接口&#xff09;&#xff0c;又可以連接交換機間的干道鏈路&#xff08;類似于Trunk接口&#xff09;。它允許多個VLAN的幀通過&#xff0c;并可以在出接口方向將某些VLAN幀的標簽剝掉&#xff0…

Tensor 基本操作1 | PyTorch 深度學習實戰

目錄 創建 Tensor常用操作unsqueezesqueezeSoftmax代碼1代碼2代碼3 argmaxitem 創建 Tensor 使用 Torch 接口創建 Tensor import torch參考&#xff1a;https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html 常用操作 unsqueeze 將多維數組解套&#xf…

Grafana系列之面板接入Prometheus Alertmanager

關于Grafana的儀表板Dashboard&#xff0c;以及面板Panel&#xff0c;參考Grafana系列之Dashboard。可以直接在面板上創建Alert&#xff0c;即所謂的Grafana Alert&#xff0c;參考Grafana系列之Grafana Alert。除了Grafana Alert外&#xff0c;面板也可接入Prometheus Alertma…

Windows 上安裝 MongoDB 的 zip 包

博主介紹&#xff1a; 大家好&#xff0c;我是想成為Super的Yuperman&#xff0c;互聯網宇宙廠經驗&#xff0c;17年醫療健康行業的碼拉松奔跑者&#xff0c;曾擔任技術專家、架構師、研發總監負責和主導多個應用架構。 近期專注&#xff1a; RPA應用研究&#xff0c;主流廠商產…

LeetCode 2266.統計打字方案數:排列組合

【LetMeFly】2266.統計打字方案數&#xff1a;排列組合 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/count-number-of-texts/ Alice 在給 Bob 用手機打字。數字到字母的 對應 如下圖所示。 為了 打出 一個字母&#xff0c;Alice 需要 按 對應字母 i 次&#xff0c…

PTA乙級1001~1005【c++】

首先講解一下PTA乙級在哪里。PTA乙級題其實就是PAT (Basic Level) Practice &#xff08;中文&#xff09; 1001 害死人不償命的(3n1)猜想 #include<iostream> using namespace std;int main() {int cnt 0;int n;cin >> n;while(n ! 1){cnt ;if (n & 1){n …

滲透筆記1

第一天 工具&#xff1a;cs cobalt strike 4.9 / msf kali &#xff08;自帶 Ubuntu&#xff09; cs cobalt strike 4.9&#xff1a;server-client server部署在云服務器上&#xff0c;client分別在各地&#xff0c;與server相連接&#xff1b;連接上后就可以共享上線主機。…

用Python實現SVM搭建金融反詐模型(含調試運行)

1.概述 信用卡盜刷一般發生在持卡人信息被不法分子竊取后&#xff0c;復制卡片進行消費或信用卡被他人冒領后激活并消費等情況下。一旦發生信用卡盜刷&#xff0c;持卡人和銀行都會遭受一定的經濟損失。本節要運用支持向量機分類算法搭建一個金融反欺詐模型。 2.數據集 使用…

HunyuanVideo 文生視頻模型實踐

HunyuanVideo 文生視頻模型實踐 flyfish 運行 HunyuanVideo 模型使用文本生成視頻的推薦配置&#xff08;batch size 1&#xff09;&#xff1a; 模型分辨率(height/width/frame)峰值顯存HunyuanVideo720px1280px129f60GHunyuanVideo544px960px129f45G 本項目適用于使用 N…

第6章 ThreadGroup詳細講解(Java高并發編程詳解:多線程與系統設計)

1.ThreadGroup 與 Thread 在Java程序中&#xff0c; 默認情況下&#xff0c; 新的線程都會被加入到main線程所在的group中&#xff0c; main線程的group名字同線程名。如同線程存在父子關系一樣&#xff0c; Thread Group同樣也存在父子關系。圖6-1就很好地說明了父子thread、父…

nginx常用配置 (含負載均衡、反向代理、限流、Gzip壓縮、圖片防盜鏈 等示例)

nginx的配置文件通常在 /etc/nginx/nginx.conf , /etc/nginx/conf.d/*.conf 中&#xff0c; 一般直接 改 conf.d目錄下的 default.conf文件&#xff0c; 然后 先檢測配置文件是否有錯誤 nginx -t 再重新加載配置文件 或 重啟nginx&#xff0c;命令如下 nginx -s reload 或…

Python編程與在線醫療平臺數據挖掘與數據應用交互性研究

一、引言 1.1 研究背景與意義 在互聯網技術飛速發展的當下,在線醫療平臺如雨后春筍般涌現,為人們的就醫方式帶來了重大變革。這些平臺打破了傳統醫療服務在時間和空間上的限制,使患者能夠更加便捷地獲取醫療資源。據相關報告顯示,中國基于互聯網的醫療保健行業已進入新的…

Linux網絡_套接字_UDP網絡_TCP網絡

一.UDP網絡 1.socket()創建套接字 #include<sys/socket.h> int socket(int domain, int type, int protocol);domain (地址族): AF_INET網絡 AF_UNIX本地 AF_INET&#xff1a;IPv4 地址族&#xff0c;適用于 IPv4 協議。用于網絡通信AF_INET6&#xff1a;IPv6 地址族&a…

1 行命令引發的 Go 應用崩潰

一、前言 不久前&#xff0c;阿里云 ARMS 團隊、編譯器團隊、MSE 團隊攜手合作&#xff0c;共同發布并開源了 Go 語言的編譯時自動插樁技術。該技術以其零侵入的特性&#xff0c;為 Go 應用提供了與 Java 監控能力相媲美的解決方案。開發者只需將 go build 替換為新編譯命令 o…