Linux操作系統學習之---進程狀態

? ? ? ?

目錄

? ? ? ? 明確進程的概念:

? ? ? ?

Linux下的進程狀態:

????????虛擬終端的概念:

?????????見一見現象:

????????用途之一 : 結合指令來監控進程的狀態:

和進程強相關的系統調用函數接口:

????????getpid()和getppid():

? ? ? ? fork():

????????fork函數創建子進程的分流邏輯:?

? ? ? ? 進程之間具有獨立性:?

?????????進程中存在的寫時拷貝:

見一見進程狀態:? ? ? ?

??在代碼層面見一見R和S兩種狀態:

????????系統調用函數 getpid() 和 getppid()

? ? ? ? 代碼和實操:?

? ? ? ? ?出現的疑點:

在代碼層面見一見 Z狀態:

????????概念理解:

? ? ? ? ?代碼實踐:

粗略了解一下D狀態:

補充說明X和T狀態:

在文件層面見一見進程:

特殊的進程:孤兒進程

? ? ? ? 驗證代碼:?

? ? ? ? 見一見效果:?

? ? ? ? ?最終的去處:


在籠統的認識了整個操作系統之后,就可以挑一個局部開始學習. 進程就是一個很好的選擇 , 他就想一個不知疲倦的員工,等待著使用者發號施令 . 我們的每一個操作,最終能夠起到作用都是以來著一個個進程 , 所以他也是離我們最近的元素 .?

? ? ? ? 明確進程的概念:

??????? 一切程序最開始都是乖乖待在磁盤里的一堆二進制文件 , 當打開電腦后 , 不管是系統內置的程序 , 還是我們自己的程序 , 加載到內存 , 就變成了進程

? ? ? ? 具體來講 , 當加載一個程序時 , 原本在磁盤里的代碼和數據被加載到內存 , 經過操作系統的無形大手 , 將這一堆內容定義成了統一的格式---結構體(操作系統底層通常都是c語言) .

? ? ? ? 因此 , 真正稱得上進程并非單純的"程序"這一抽象概念 , 而是進程控制塊PCB(結構體實例化處的對象 Process Control BLOCK) + 代碼和數據 .

? ? ? ? 我們管理一個進程 , 本質上就是對操作系統發號施令,讓他來管理這兩個內容.

? ? ? ?

Linux下的進程狀態:

運行(R)指的是處于調度隊列里的進程
可中斷睡眠(S)又稱作阻塞,通常是在等待各種事件時的狀態
不可中斷睡眠(D)

通常是在等待IO操作時的狀態

停止(T)比如我們按下Ctrl+z , 一個前臺進程就停止了
死亡(X)這個狀態一般我們看不到

????????虛擬終端的概念:

? ? ? ? ?由于咱通常都是用windows電腦來學習Linux操作系統,所以配置虛擬機啥的比較麻煩 , 索性就用xshell之類的外殼程序來連接云服務器進行操作?.?

? ? ? ? 而一臺云服務器可以同時供多個用戶使用 , 甚至 , 同一個用戶還可以同時打開兩個終端同時對一臺機器進行操作 , 看著是不是有些讓人匪夷所思 ,下面簡單解釋一下子:

?????????見一見現象:

?現象:

?只打開一個終端時:

用同一個用戶多開一個終端時:?

????????用途之一 : 結合指令來監控進程的狀態:

? ? ? ? 比方說我們初次學習進程,了解了一堆概念 , 那么久可以開一個終端窗口用于運行我們的程序 , 開第二個窗口用于監控我的的程序狀態(程序運行起來后就是一個進程)

和進程強相關的系統調用函數接口:

????????getpid()和getppid():

? ? ? ? 這倆哥們很簡單 , getpid()函數返回當前進程的pid ;? getppid()返回父進程的pid

? ? ? ? fork():

? ? ? ? 這個函數相較于c語言的大部分函數來說都很神奇 , 調用它就會為當前進程創建一個子進程 , 而我們知道子進程創建出來是為父進程分擔任務的 , 這就涉及到它的三個返回值了

????????fork函數創建子進程的分流邏輯:?

? ? ? ? fork有三個返回值:

  1. ?如果是父進程 , 返回整數
  2. 如果是子進程 , 返回0
  3. 如果創建子進程失敗 , 返回負數

? ? ? ? 因此雖然父子進程擁有一樣的代碼 , 但fork的返回值不會騙人 , 只要我們自己在代碼里對fork()的返回值進行判斷 , 根據返回值的不同執行不同的代碼 , 就可以達到代碼分流的目的了

? ? ? ? 簡單來說

? ? ? ? 進程之間具有獨立性:?

? ? ? ? 上圖中的父子進程似乎執行的是同一段代碼 , 只是不同的部分 , 其實父進程和子進程是完全獨立的 , 他們具有不同的pid.

? ? ? ? 之所以可以執行同一塊代碼 , 只是因為代碼本身在程序運行期間是只讀的 , 存放在代碼區, 不屬于任何進程自己的的內容?, 因此父子進程都可以訪問同一段代碼(保存同樣的指針)

?????????進程中存在的寫時拷貝:

? ? ? ?盡管進程之前是獨立的,但是在剛剛創建子進程時 , 為了提升效率 , 子進程新創建的PCB的內容幾乎是從父進程那完完全全拷貝而來的(除了pid等等比較特殊的屬性才會不同).

????????當調用fork函數時,會創建一個當前進程的子進程 , 子進程會擁有和當前進程同樣的代碼和數據.

? ? ? ? 代碼是存在于代碼區帶只讀內容 , 父、子進程只需要保存相同的指針變量指向對應的代碼即可

? ? ? ? 而數據不同 ,尤其是變量 ,可能需要被頻繁的修改 ,為了避免多個進程各自修改同一個變量對其他進程造成影響 , 就有了寫時拷貝的設計

? ? ? ? 一旦涉及數據的修改 , 操作系統就會為修改數據的進程新開辟一塊空間 , 拷貝一份原來的數據讓他進行自己的操作 .?

? ? ? ? 這就像"借鑒"同學的作業一樣 , 你只是看看還好 , 如果你想要修改 , 哪怕只是改一下名字 , 也得你自己另外弄一份來改!!!

見一見進程狀態:? ? ? ?

??在代碼層面見一見R和S兩種狀態:

????????系統調用函數 getpid() 和 getppid()

? ? 定義在<unistd.h>頭文件中 , getpid會返回當前進程(運行的程序)的進程pid , pid是一個進程的唯一標識符, 類似于一個學生的學號 .

? ? getppid()則會返回當前進程(運行的程序)的父進程的pid , 當前的進程稱為子進程 , 由父進程來創建這個進程. 就好像上級領導吩咐了一個下屬來幫自己干活.

? ? ? ? 接下來寫一個死循環程序 , 其中使用了一個死循環來不停的調用getpid()和getppid()來打印子進程和父進程的pid( )

? ? ? ? 接著打開第二個窗口來監視他的狀態

????????用于監視的指令 :?while true; do ps -ajx | head - | ps -ajx | grep code; sleep 1; done

????????其中code是我將要執行的程序

? ? ? ? 代碼和實操:?

#include<unistd.h> //類unix操作系統相關函數的頭文件,此處用于getpid()和getppid()while(1){printf("我是一個進程,我的pid:%d , 我的ppid:%d\n",getpid(),getppid());sleep(1);}

? ? ? ? ?出現的疑點:

  1. ? ? ? ?在剛才的程序里 , 明明是好像一直在一秒一秒的打印內容 , 為啥進程的狀態是S+ 呢? 其實和S狀態的定義和sleep函數有關:
  2. ? ? ? ? S狀態稱為可中斷睡眠狀態 , 通常發生在進程等待某種指令的間隙?
  3. ? ? ? ? 我的程序里有sleep函數 , 是的每次執行完一次printf后就會等待一秒
  4. ? ? ? ? 可是printf進行打印的操作相較于sleep的1秒來說實在是太短了,以至于ps指令幾乎沒法捕捉到進程進行輸出時的狀態(R+)
  5. ? ? ? ? 如果想要看到程序為運行狀態 , 只需要去掉sleep ,讓進程頻繁的進行打印.

? ? ? ? ?當去掉了代碼和監控指令里的sleep后,總算是可以觀察到R+狀態了哈哈哈哈哈.

在代碼層面見一見 Z狀態:

????????概念理解:

? ? ? ? Z(zombie)狀態叫做僵尸狀態 , 十分形象 :

????????想象一個人突然倒在路邊 , 沒有了呼吸 , 可以當叫來警察和救護車后 , 并不會直接把人抬走然后通知家屬 , 而是讓醫生先檢測和搶救一下 , 如果沒有這個過程 , 貿然帶走尸體甚至是違法的 .?

? ? ? ? 醫生進行檢測和搶救的過程 , 就是父進程回收子進程退出(死亡)信息的過程 , 如果沒有回收 , 誰也不敢貿然處理(即不能釋放這個進程的PCB) , 因此尸體在躺在地上的時候就會污染環境和占據空間(即遲遲不釋放的PCB會占用內存空間).

? ? ? ? 結論 : 當一個進程的使命結束 , 就會變成僵尸狀態 , 如果沒有父進程來獲取他的退出信息 , 這個僵尸進程就會一直占用內存空間 ,造成空間浪費.

? ? ? ? ?代碼實踐:

? ? ? ? 下面的代碼讓父進程一直運行 , 而子進程執行一條printf函數后就結束:

int ret = fork();if(ret > 0)//父進程{while(1){printf("我是父進程,pid:%d,我在😪\n",getpid());sleep(1);}}else if(ret == 0)//子進程{printf("我是子進程,pid:%d,我很快就要掛了....💀\n",getpid());}else  //創建子進程失敗{//失敗的情況很少見}

?????????下面是運行的內容和進程的監控內容?

粗略了解一下D狀態:

定義 : 不可中斷休眠 , 通常回出現在一個進程等待IO操作時 , 可以在一定程度上避免數據丟失

??????????這個很難驗證 , 但可以文字敘述一下(情況之一):

  • ????????系統的內存資源是有限的 , 因此操作系統會在系統資源告急時采取一些策略 , 將不那么重要的進程的大部分內容給暫時移走
  • ? ? ? ? 當系統的資源告急時很嚴重了 , 為了表面上給用戶一個良好的使用體驗 , 除了看得見的前臺進程?, 其他的不分青紅皂白就會給殺掉!!!
  • ? ? ? ? 可是有的進程可能正在對磁盤里面寫入數據 , 接著等待磁盤的處理結果 , 這時如果進程被殺掉了 , 不管寫入數據是否成功 , 磁盤的處理結果可能就會丟失 , 用戶層面對此是全然不知的!!!
  • ? ? ? ? 因此對于進行IO操作的進程 , 比如開個后門 , 讓它們可以平平安安的獲取操作的結果 , 也就有了D狀態 , 故而也叫磁盤休眠狀態.?

補充說明X和T狀態:

? ? ? ? X狀態 : 一個死透了的進程 , 通常上層用戶看不見 , 畢竟后事處理完后就沒有為他留著內存空間的必要了 . (上面提到過的僵尸進程就是還沒死透但還需要被處理的進程)

? ? ? ? ?T狀態:一個暫停了的進程 , 比如當使用Ctrl +z時就會導致進程停止 , 如果放著不管就會一直占用空間 , 造成資源浪費!!!

在文件層面見一見進程:

? ? ? ? Linux的一大設計理念---一切皆文件 . 連時而創建,時而銷毀的進程也不例外

?系統根目錄下的一個proc目錄存放了和進程相關的文件:

如果隨便查看一個管理進程的目錄文件的內容 , 結果如下 :

當然嘍,如果是查看自己的進程的路徑(比如自己運行的c語言程序) , 情況會變化

特殊的進程:孤兒進程

? ? ? ? 在驗證僵尸進程時 , 情況是子進程先于父進程結束 , 而如果是父進程先結束后留下孤零零的子進程會怎么樣呢? 答案是孤兒進程,名字也很形象啦.

? ? ? ? 驗證代碼:?

//父進程立馬結束,子進程死循環一直干活
int ret = fork();if(ret > 0)//父進程{printf("我是父進程,pid:%d,我馬上溜啦🏃?♂?💨\n",getpid());}else if(ret == 0)//子進程{while(1){printf("我是子進程,pid:%d,我在等我爸開路虎來接我😎\n",getpid());sleep(1);}}else  //創建子進程失敗{//失敗的情況很少見}

? ? ? ? 見一見效果:?

? ? ? ? 當運行程序 , 我們可以看到子進程的父進程的pid馬上變成了1 , 并且 , 無法用Ctrl+c來殺掉這個進程!!!如下圖:?

? ? ? ? ?pid為1的進程是最重要的系統進程(Linux下叫做init) , 甚至可以把他就當做操作系統本身 .(其實還有pid為0的進程,只不過在創建1號進程后很快就結束了)

? ? ? ? 當父進程先于子進程退出 , 那后續子進程結束后就沒有進程可以獲取他的退出信息 , 從而就永遠無法被銷毀 , 這時就會由pid為1的系統進程來收養他 , 因此父進程提前退出的子進程也叫做孤兒進程

? ? ? ? ?最終的去處:

? ? ? ? 孤兒進程被pid為1的init系統進程收養后 , 還會變成后臺進程 , 無法被ctrl+c(針對前臺進程)給終止 , 但可以使用 kill -9 pid來殺掉 .否則 , 系統不停止運行 , 這個子進程就會一直占用內存資源

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

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

相關文章

何小鵬在得意的笑

"小鵬汽車率先邁出了造車新勢力出海一大步" 作者 | 魏強 編輯 | 盧旭成 4月15日&#xff0c;小鵬汽車在香港舉行小鵬全球熱愛之夜和2025首款全球旗艦小鵬X9上市發布會。 當小鵬汽車創始人何小鵬把香車X9交付給香港首批車主的時候&#xff0c;臉上露出經典的笑臉。…

@Autowird 注解與存在多個相同類型對象的解方案

現有一個 Student 類&#xff0c;里面有兩個屬性&#xff0c;分別為 name 和 id&#xff1b;有一個 StuService 類&#xff0c;里面有兩個方法&#xff0c;返回值均為類型為 Student 的對象&#xff1b;還有一個 StuController 類&#xff0c;里面有一個 Student 類型的屬性&am…

黑馬商城項目(三)微服務

一、單體架構 測試高并發軟件 二、微服務 三、SpringCloud 四、微服務拆分 黑馬商城模塊&#xff1a; 服務拆分原則&#xff1a; 拆分服務&#xff1a; 獨立project&#xff1a; maven聚合&#xff1a; 拆分案例&#xff1a; 遠程調用&#xff1a; package com.hmall.cart.…

PyTorch:學習 CIFAR-10 分類

&#x1f50d; 開始你的圖像分類之旅&#xff1a;一步一步學習 CIFAR-10 分類 圖像分類是計算機視覺中最基礎的任務之一&#xff0c;如果你是初學者&#xff0c;那么以 CIFAR-10 為訓練場是一個不錯的選擇。本文一步一步帶你從零開始&#xff0c;學習如何用深度學習模型實現圖…

3.學習筆記--Spring-AOP總結(p39)-Spring事務簡介(P40)-Spring事務角色(P41)-Spring事務屬性(P42)

1.AOP總結&#xff1a;面向切面編程&#xff0c;在不驚動原始基礎上為方法進行功能增強。 2.AOP核心概念&#xff1a; &#xff08;1&#xff09;代理&#xff1a;SpringAOP的核心是采用代理模式 &#xff08;2&#xff09;連接點&#xff1a;在SpringAOP中&#xff0c;理解為任…

數據庫-day06

一、實驗名稱和性質 分類查詢 驗證 綜合 設計 二、實驗目的 1&#xff0e;掌握數據查詢的Group by &#xff1b; 2&#xff0e; 掌握聚集函數的使用方法。 三、實驗的軟硬件環境要求 硬件環境要求&#xff1a; PC機(單機) 使用的軟件名稱、版本號以及模塊&#xff1a; …

看門狗定時器(WDT)超時

一、問題 Arduino 程序使用<Ticker.h>包時&#xff0c;使用不當情況下&#xff0c;會導致“看門狗WDT超時” 1.1問題控制臺報錯 在串口監視器顯示 --------------- CUT HERE FOR EXCEPTION DECODER ---------------Soft WDT resetException (4): epc10x402077cb epc2…

AI在多Agent協同領域的核心概念、技術方法、應用場景及挑戰 的詳細解析

以下是 AI在多Agent協同領域的核心概念、技術方法、應用場景及挑戰 的詳細解析&#xff1a; 1. 多Agent協同的定義與核心目標 多Agent系統&#xff08;MAS, Multi-Agent System&#xff09;&#xff1a; 由多個獨立或協作的智能體&#xff08;Agent&#xff09;組成&#xff…

Wireshark TS | 異常 ACK 數據包處理

問題背景 來自于學習群里群友討論的一個數據包跟蹤文件&#xff0c;在其中涉及到兩處數據包異常現象&#xff0c;而產生這些現象的實際原因是數據包亂序。由于這兩處數據包異常&#xff0c;都有點特別&#xff0c;本篇也就其中一個異常現象單獨展開說明。 問題信息 數據包跟…

【React】項目的搭建

create-react-app 搭建vite 搭建相關下載 在Vue中搭建項目的步驟&#xff1a;1.首先安裝腳手架的環境&#xff0c;2.通過腳手架的指令創建項目 在React中有兩種方式去搭建項目&#xff1a;1.和Vue一樣&#xff0c;先安裝腳手架然后通過腳手架指令搭建&#xff1b;2.npx create-…

深入淺出 NVIDIA CUDA 架構與并行計算技術

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、CUDA為何重要&#xff1a;并行計算的時代 2、NVIDIA在…

pytorch學習02

自動微分 自動微分模塊torch.autograd負責自動計算張量操作的梯度&#xff0c;具有自動求導功能。自動微分模塊是構成神經網絡訓練的必要模塊&#xff0c;可以實現網絡權重參數的更新&#xff0c;使得反向傳播算法的實現變得簡單而高效。 1. 基礎概念 張量 Torch中一切皆為張…

Java虛擬機(JVM)平臺無關?相關?

計算機的概念模型 計算機實際上就是實現了一個圖靈機模型。即&#xff0c;輸入參數&#xff0c;根據程序計算&#xff0c;輸出結果。圖靈機模型如圖。 Tape是輸入數據&#xff0c;Program是針對這些數據進行計算的程序&#xff0c;中間橫著的方塊表示的是機器的狀態。 目前使…

satoken的奇奇怪怪的錯誤

發了 /user/getBrowseDetail和/user/getResponDetail&#xff0c;但為什么進入handle里面有三次&#xff1f;且第一次的handle類型是AbstractHandleMapping$PreFlightHttpRequestHandlerxxx,這一次進來的時候flag為false&#xff0c;StpUtils.checkLogin拋出了異常 第二次進來的…

【KWDB 創作者計劃】_上位機知識篇---SDK

文章目錄 前言一、SDK的核心組成API(應用程序接口)庫文件(Libraries)開發工具文檔與示例依賴項與環境配置二、SDK的作用簡化開發流程確保兼容性與穩定性加速產品迭代功能擴展與定制三、SDK的典型應用場景硬件設備開發操作系統與平臺云服務與API集成游戲與圖形開發四、SDK與…

golang處理時間的包time一次性全面了解

本文旨在對官方time包有個全面學習了解。不鉆摳細節&#xff0c;但又有全面了解&#xff0c;重點介紹常用的內容&#xff0c;一些低頻的可能這輩子可能都用不上。主打一個花最少時間辦最大事。 Duration對象: 兩個time實例經過的時間,以長度為int64的納秒來計數。 常見的durati…

PyCharm Flask 使用 Tailwind CSS 配置

使用 Tailwind CSS 步驟 1&#xff1a;初始化項目 在 PyCharm 終端運行&#xff1a;npm init -y安裝 Tailwind CSS&#xff1a;npm install -D tailwindcss postcss autoprefixer初始化 Tailwind 配置文件&#xff1a;npx tailwindcss init這會生成 tailwind.config.js。 步…

【英語語法】基本句型

目錄 前言一&#xff1a;主謂二&#xff1a;主謂賓三&#xff1a;主系表四&#xff1a;主謂雙賓五&#xff1a;主謂賓補 前言 英語基本句型是語法體系的基石&#xff0c;以下是英語五大基本句型。 一&#xff1a;主謂 結構&#xff1a;主語 不及物動詞 例句&#xff1a; T…

隔離DCDC輔助電源解決方案與產品應用科普

**“隔離”與“非隔離的區別** 隔離&#xff1a; 1、AC-DC&#xff0c;也叫“一次電源”&#xff0c;人可能會碰到的應用場合&#xff0c;起安全保護作用&#xff1b; 2、為了抗干擾&#xff0c;通過隔離能有效隔絕干擾信號傳輸。 非隔離&#xff1a; 1、“安全特低電壓&#…

DS-SLAM 運動一致性檢測的源碼解讀

運動一致性檢測是Frame.cc的Frame::ProcessMovingObject(const cv::Mat &imgray)函數。 對應DS-SLAM流程圖Moving consistency check的部分 把這個函數單獨摘出來&#xff0c;寫了一下對兩幀檢測&#xff0c;查看效果的程序&#xff1a; #include <opencv2/opencv.hpp…