Linux(7)——進程(概念篇)

一、基本概念

書本上的概念:程序的一個執行實例,正在執行的程序等

基于內核的觀點:擔當分配系統資源(CPU時間,內存)的實體。?

我們知道,我們在寫代碼的時候,你的代碼進行編譯鏈接后生成可執行文件,這個文件就在磁盤當中,當我們雙擊這個文件之后,該文件就被加載到了內存之中,因為只有加載到了內存之中才能被cpu逐語句執行。而加載了內存中的程序,不再是程序而應該是進程。?

二、描述進程——PCB

實際上我們在系統當中有很多的進程,我們可以通過ps aux命令來查看:

我們知道操作系統是第一個被加載到內存的,而操作系統就是做的管理工作的,那么操作系統是怎么做到管理的呢?

這里就用到了之前在談操作系統時候提到的六個字:先描述,再組織。操作系統作為管理者,是不需要與進程直接交互的,當進程到來時,操作系統需要對進程進行描述,那么對進程的管理就變成了對描述的管理。進程的描述信息會被放到一個叫進程描述塊之中,官方稱之為PCB(process control block)。

操作系統將每一個進程都進行描述,形成了一個個的進程控制塊(PCB),并將這些PCB以雙鏈表的形式組織起來:

這樣一來,操作系統只要拿到這個雙鏈表的頭指針,便可以訪問到所有的PCB。此后,操作系統對各個進程的管理就變成了對這條雙鏈表的一系列操作。
例如創建一個進程實際上就是先將該進程的代碼和數據加載到內存,緊接著操作系統對該進程進行描述形成對應的PCB,并將這個PCB插到該雙鏈表當中。而退出一個進程實際上就是先將該進程的PCB從該雙鏈表當中刪除,然后操作系統再將內存當中屬于該進程的代碼和數據進行釋放或是置為無效。
總的來說,操作系統對進程的管理實際上就變成了對該雙鏈表的增、刪、查、改等操作。?

1.task_struct——PCB的一種

因為Linux是拿C語言寫的,那么這里的task_struct其實是一個結構體。

1)在Linux中描述進程的結構體叫做task_struct。
2)task_struct是Linux內核的一種數據結構,它會被裝載到RAM(內存)里并且包含著進程的信息。

2.task_struct的內容分類

主要內容:

  • 標示符:描述本進程的唯一標示符,用來區別其他進程
  • 狀態: 任務狀態,退出代碼,退出信號等。
  • 優先級:相對于其他進程的優先級。
  • 程序計數器:程序中即將被執行的下一條指令的地址。
  • 內存指針:包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針
  • 上下文數據: 進程執行時處理器的寄存器中的數據[休學例子,要加圖CPU,寄存器]。
  • 1/0狀態信息:包括顯示的I/0請求,分配給進程的!/0設備和被進程使用的文件列表。
  • 記賬信息:可能包括處理器時間總和,使用的時鐘數總和,時間限制,記賬號等。
  • 其他信息

三、查看進程

1.通過系統目錄查看

我們除了上面的,通過ps aux命令查看以外,還可以在根目錄下找系統文件夾proc。

我們打開文件夾,可以看到一些以數字命名的目錄

這些數字就是我們之前所說的PID,在對應的目錄中記錄了進程的相關信息,比如我們查看1的文件內容:

2.通過ps命令查看

單獨使用ps:

ps aux

ps結合grep可以看到更加標準的進程信息:

四、通過系統調用獲取進程的PID和PPID?

這里我們要用到兩個調用函數,分別是getpid()和getppid()來分別獲取PID和PPID。

我們可以寫個代碼來測試一下:

輸出:?

我們也可以看一看進程的信息是不是和我們調用函數獲取的一致

五、通過系統調用創建進程

1.fork函數創建子進程

fork函數是一個系統調用函數,他可以創建一個子進程:

例如:

運行結果如下:

運行結果中的第一行數據是該進程的PID和PPID,第二行是、fork函數創建的PID和PPID,不難發現fork函數創建的進程的PPID就是proc的PID,也就是說proc進程和fork創建的進程是父子關系。

沒出現一個進程,操作系統都會為其創建PCB,fork也不例外。

我們知道加載到內存的代碼和數據是父進程的,那么fork創建的子進程的代碼和數據是哪里來的呢?

我們來寫個代碼來看看:

運行結果:

實際上,fork函數創建子進程,在fork函數之前的代碼要被父進程執行,而fork()之后的代碼默認是父子進程都可以執行的。

敲黑板:

1)這里雖然是父子進程代碼共享,但是父子進程各自開辟空間(寫時拷貝)。

2)這里面可能大家都會有一個疑問,那就是這里父子進程的執行順序是什么樣的,其實這里執行的順序完全是不確定的,取決于操作系統的調度。

2.使用if來引出問題

我們在之前說了,在fork()函數之后的父子進程共享代碼,那么這樣一來,我們創建子進程就沒有了意義,實際上使用的時候是要使用if來分流的,也就是父子進程去做不同的事情。

fork的返回值:

1.如果子進程創建成功了,在父進程中返回子進程的PID,而在子進程中返回0。

2.如果子進程創建失敗,則父進程中返回。

既然子進程創建的返回值不一樣,那么我們就可以通過這個性質來分流。

代碼如下:

運行結果:

六、Linux的進程狀態

進程從創建開始到被系統清理消亡的這個時間里,有時會占用CPU,有時在等待CPU分配資源,從這里看,進程是不同于程序的,進程有著自己動態變化的狀態。下面的這個圖就是我們待會要說明的。

我們可以看看在Linux中的進程狀態的內容,下面是Linux內核的部分源代碼:

/*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/static const char *const task_state_array[] = {"R (running)", /*0 */"S (sleeping)", /*1 */"D (disk sleep)", /*2 */"T (stopped)", /*4 */"t (tracing stop)", /*8 */"X (dead)", /*16 */"Z (zombie)", /*32 */};

敲黑板:

這里的進程狀態實際上是保存在進程控制塊(PCB)中的,而在Linux中就是保存在了task_struct中的。

?在Linux中我們可以使用ps aux和ps axj來查看進程的狀態。

ps aux

ps axj

1.運行狀態——R

這個狀態(Runing)不一定就是進程處在運行當中,也有可能是在運行隊列當中,也就是說系統中可以同時有多個處于R狀態的進程。

敲黑板:

所有處于這個狀態的進程,都是可以被調度的,他們在運行隊列當中,在操作系統需要切換進程時,可以在這個里面直接選取。?

2.淺度睡眠狀態——S?

一個進程處于淺度睡眠狀態(sleeping),意味著該進程在等待事件的完成,這時的進程是可以被隨時喚醒的(和人一樣),也可以被殺亖(由于這個原因,這個狀態也被叫做可中斷睡眠(interruptible sleep)。

我們可以寫個代碼來演示一下:

這里我們讓程序休眠100秒來模擬進程處于淺度睡眠狀態。

ps aux | head -1 && ps aux | grep test | grep -v grep

之前說過處于這個狀態的進程是可以被殺亖的,我們來看看:

3.深度睡眠狀態——D

一個進程處于深度睡眠狀態(disk sleep),表示這個進程是不可以被殺亖的,即使是操作系統也不行,只能該進程自動喚醒才可以恢復。所以這個狀態也可以被叫做是不可中斷睡眠(uninterruptible sleep),處在這個狀態的進程通常需要等待IO的結束。

其實我們通過他的英文也可以知道,他肯定適合磁盤(disk)相關的,具體的場景就是要向硬盤中寫數據,這個過程是不能被殺亖的,因為我們等待磁盤的回復(是否寫入完畢)來做出反應(磁盤處于休眠狀態)。

4.暫停狀態——T

在Linux中我們可以發送SIGSTOP信號讓進程處于暫停狀態(stopped),發送SIGCONT信號讓處于暫停狀態的進程重新運行起來。

例如:

我們發送一個SIGSTOP信號給test讓進程處于暫停狀態。

然后我們再發送一個SIGCONT信號讓進程重新運行,這里運行的時候盡量快一點,因為時間一代程序就結束了:

補充說明:

我們可以使用kill -l命令來列出命令集

kill -l

5.僵尸狀態——Z

一個進程在要退出時,在系統層面,并不是我們想的直接就釋放資源,而是會保存一段時間,來供操作系統或父進程讀取退出信息,如果沒有讀取到相關的退出信息,那么數據也不會被釋放,一個進程在等待數據被釋放的過程就是處于僵尸狀態(zombie)。

我們通過上面的描述也能知道僵尸狀態其實是很必要的,因為進程就是去被指示去做事情的,那么指示方就應該要知道被指示方的完成情況,而僵尸狀態就是指示方來獲取完成情況的。

例如:我們之前一直在寫的return 0;實際上這個0就是返回給給操作系統的,讓操作系統知道我們完成的情況。在Linux中我們可以通過打印$?來獲取最近一個進程的退出碼。

echo $?

敲黑板:

和運行狀態一樣,這個退出碼也是被保存在PCB中的,在Linux中就是在task_struct中。

6.死亡狀態?

死亡狀態就是一個理論上的返回狀態,當一個進程的退出信息被讀取后,該進程申請的資源就被釋放掉了,那么該進程也就不存在了,所以我們不可能在我們列出來的信息中看到死亡狀態。

七、僵尸進程

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

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

相關文章

【Harmony】【鴻蒙】List列表View如何刷新內部的自定義View的某一個控件

創建自定義View Component export struct TestView{State leftIcon?:Resource $r(app.media.leftIcon)State leftText?:Resource | string $r(app.string.leftText)State rightText?:Resource | string $r(app.string.rightText)State rightIcon?:Resource $r(app.med…

Docker安裝MySQL集群(主從復制)

為確保生產環境中的數據安全與可靠性,數據庫普遍采用主從集群架構(一主一從)進行部署。本文將系統闡述如何利用Docker鏡像實現數據庫集群的容器化部署,并完整記錄各配置環節的具體實現步驟。 一、主服務實例創建(可以…

開篇:MCP理論理解和學習

文章目錄 零 參考資料一 MCP概念二 MCP核心架構和功能三 MCP VS OP(Others Protocol)3.1 函數調用3.2 模型上下文協議3.3 MCP VS Others Protocol3.3.1 MCP與Function Calling的對比優勢3.3.2 MCP與AI Agents的協同關系3.3.3 MCP與A2A協議的互補性3.3.4 MCP與傳統API的技術革新…

產品經理面經(三)

目錄 為什么想做產品經理?為什么適合做產品經理? 解析 我的回答: 你覺得產品經理應該具備什么品質 解析 我的回答 想做什么方向的產品經理呢&你知道產品經理分為哪幾種嗎? 解題思路 為什么想做產品經理?為…

Vue3 Composition API: 企業級應用最佳實踐方案

在當前前端技術迅速發展的環境下,Vue3 Composition API 成為了關注的焦點。它為開發人員提供了更加靈活和可維護的代碼結構,適用于構建大規模企業級應用。在本文中,我們將探討Vue3 Composition API的最佳實踐方案,幫助開發人員更好…

CentOS大師班:企業級架構與云端融合實戰

一、高級存儲管理與災難恢復 1. LVM動態卷擴展實戰 pvcreate /dev/sdb1 # 創建物理卷 vgcreate vg_data /dev/sdb1 # 創建卷組 lvcreate -L 100G -n lv_www vg_data # 創建邏輯卷 mkfs.xfs /dev/vg_data/lv_www # 格式化 mount /dev/vg_da…

使用VGG-16模型來對海賊王中的角色進行圖像分類

動漫角色識別是計算機視覺的典型應用場景,可用于周邊商品分類、動畫制作輔助等。 這個案例是一個經典的深度學習應用,用于圖像分類任務,它使用了一個自定義的VGG-16模型來對《海賊王》中的七個角色進行分類,演示如何將經典CNN模型…

[創業之路-377]:企業戰略管理案例分析-戰略制定/設計-市場洞察“五看”:看宏觀之社會發展趨勢:數字化、智能化、個性化的趨勢對初創公司的戰略機會

數字化、智能化、個性化趨勢為初創公司帶來了捕捉長尾需求、提升運營效率、創新商業模式等戰略機會,具體分析如下: 一、數字化趨勢帶來的戰略機會 捕捉長尾需求:數字化技術能夠幫助初創公司更好地捕捉市場中的長尾需求,滿足那些…

macOS 安裝 PostgreSQL

文章目錄 安裝安裝信息 驗證GUI 工具下載 安裝 最簡單的方式是通過 brew 安裝 brew install postgresql17該版本在 brew 上的詳情頁:https://formulae.brew.sh/formula/postgresql17 你也可以根據需要,搜索 安裝更新版本 如果你沒有安裝 brew&#xf…

安裝openresty使用nginx+lua,openresty使用jwt解密

yum install -y epel-release yum update yum search openresty # 查看是否有可用包 yum install -y openresty啟動systemctl start openresty驗證服務狀態systemctl status openresty設置開機自啟systemctl enable openrestysystemctl stop openresty # 停止服務 system…

全球化 2.0 | 云軸科技ZStack助力中東智慧城市高性能智能安防云平臺

在全球智慧城市加速建設的背景下,中東某大型城市通過部署云軸科技ZStack Cloud云平臺,成功實現公共安全視頻監控系統(CCTV)的智能化升級。該平臺以彈性計算、GPU智能調度、高可用架構為核心,支撐千路高清視頻流處理及人…

Day35打卡 @浙大疏錦行

知識點回顧: 三種不同的模型可視化方法:推薦torchinfo打印summary權重分布可視化進度條功能:手動和自動寫法,讓打印結果更加美觀推理的寫法:評估模式 作業:調整模型定義時的超參數,對比下效果。…

嵌入式軟件-如何做好一份技術文檔?

嵌入式軟件-如何做好一份技術文檔? 文章目錄 嵌入式軟件-如何做好一份技術文檔?一.技術文檔的核心價值與挑戰二.文檔體系的結構化設計三.精準表達嵌入式特有概念四. **像管理代碼一樣管理文檔**,代碼與文檔的協同維護五.質量評估與持續改進5.…

css五邊形

五邊形 .fu{width: 172rpx;height: 204rpx;overflow: hidden;border-radius: 10rpx;clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); }六邊形 clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

【Java高階面經:微服務篇】1.微服務架構核心:服務注冊與發現之AP vs CP選型全攻略

一、CAP理論在服務注冊與發現中的落地實踐 1.1 CAP三要素的技術權衡 要素AP模型實現CP模型實現一致性最終一致性(Eureka通過異步復制實現)強一致性(ZooKeeper通過ZAB協議保證)可用性服務節點可獨立響應(支持分區存活)分區期間無法保證寫操作(需多數節點可用)分區容錯性…

頭歌軟工導論作業

一.集成測試和確認測試 第1關:集成測試 1、 集成測試的主要方法有CD A、 自頂向下集成方法 B、 自底向上集成方法 C、 漸增式測試方法 D、 非漸增式測試方法 2、 目前在進行集成測試時普遍采用非漸增式測試方法。B A、 √ B、 3、 自底向上集成策略是從主控制模…

MFC:獲取所有打印機的名稱(打印機模塊-1)

背景: 在一個 MFC 應用程序中,列出本地系統中安裝的打印機,并檢測是否存在“Microsoft Print to PDF”或“Microsoft XPS Document Writer”虛擬打印機。如果有,則選擇其中一個作為默認或后續操作對象;如果沒有&#…

設計模式-行為型模式(詳解)

模板方法 模板方法模式,它在一個抽象類中定義了一個算法(業務邏輯)的骨架,具體步驟的實現由子類提供,它通過將算法的不變部分放在抽象類中,可變部分放在子類中,達到代碼復用和擴展的目的。 復用: 所有子類可以直接復…

STM32中的IIC協議和OLED顯示屏

串口通信協議的缺點 串口通信通常需要至少三條線(TX、RX和GND),而 I2C 總線僅需要兩條信號線(SDA和SCL); 串口通信僅支持一對一通信,而 I2C 總線支持多機通信,允許單個主機與多個從…

30個性能優化方案

1.用String.format拼接字符串 不知道你有沒有拼接過字符串,特別是那種有多個參數,字符串比較長的情況。 比如現在有個需求:要用get請求調用第三方接口,url后需要拼接多個參數。 以前我們的請求地址是這樣拼接的: S…