Linux修煉之路之進程概念,fork函數,進程狀態

目錄

一:進程概念?

二:Linux中的進程概念

三:用getpid(),getppid()獲取該進程的PID,PPID

四:用fork()來創建子進程

五:操作系統學科的進程狀態?

?六:Linux中的進程狀態

接下來的日子會順順利利,萬事勝意,生活明朗-----------林辭憂

一:進程概念?

1.操作系統學科層面的概念

一個加載到內存中的程序,叫做進程;? ?正在運行的程序叫做進程

2.深層次的進程概念

對于一個操作系統不僅僅只能運行一個進程,而是可以運行很多個進程,為了更好的管理這些進程,就需要用先描述再組織的思想

因此對于任何一個進程在加載到內存當中的時候,形成真正的進程時,操作系統要先創建描述該進程(屬性)的struct結構體對象,即PCB(進程屬性的集合)----進程控制塊

PCB是在操作系統中定義的struct結構體類型。當加載進程的時候,本質上不僅僅是把對應的數據和代碼加載到內存,而且操作系統會根據描述該進程的PCB類型為當前進程創建對應的PCB對象,把該進程的相關屬性值填充完成初始化。這個PCB結構體變量是由操作系統自己形成的。

進程=內核PCB數據結構對象(描述該進程所有的屬性值)+對應的代碼和數據

在操作系統中,對于所有進程的PCB結構體對象使用雙向鏈表的方式 進行連接,在每個PCB結構體對象中包含相應的指針字段指向該進程對應的代碼和數據,此后操作系統只需對PCB對象進行管理,便可以達到管理進程的目的,這樣對于進程的管理就轉化為對這個鏈表的增刪查改

二:Linux中的進程概念

1.在Linux中描述進程的結構體叫做task_struct(Linux系統中的PCB)。

2.task_struct是Linux內核的一種數據結構,它會被裝載到RAM(內存)里并且包含著進程的信息

3.根據task_struct實例化進程對象,創建一個具體的PCB對象,再把所有對象的PCB組織起來

4.task_struct中包含的進程屬性

? ? ?標示符: 描述本進程的唯一標示符,用來區別其他進程(PID)

? ??狀態: 任務狀態,退出代碼,退出信號等

? ??優先級: 相對于其他進程的優先級

? ??程序計數器: 程序中即將被執行的下一條指令的地址

? ??內存指針: 包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針

? ??上下文數據: 進程執行時處理器的寄存器中的數據[休學例子,要加圖CPU,寄存器]

? ??I/O狀態信息: 包括顯示的I/O請求,分配給進程的I/O設備和被進程使用的文件列表

? ??其他信息

6.查詢進程信息相關指令

? ps axj 查看進程信息

? top 查看正在運行的進程信息

? ls /proc -l? :在系統當中啟動的所有進程默認在/proc目錄里,就會給相應進程在/proc目錄里創建以該進程PID命名的文件夾/目錄,在該目錄里保存了進程的大多屬性;在關機后,/proc目錄下的所有數據就都沒有了,在開機時,操作系統會自動創建這些目錄/文件,這上面顯示的所有信息是Linux操作系統用文件系統的方式把內存當中的文件/進程信息可視化出來,而且這些信息都是內存級別的

ls? /proc/進程PID -l 顯示系統當中具體動態運行的進程的相關信息

注:1.進程所對應的可執行程序是在磁盤exe目錄下的這個文件當中,所以PID對應的進程的可執行程序是可以被找到的

2.cwd:當進程在啟動時,該進程的PCB屬性里就記錄了當前Linux所在的絕對路徑,也就是當前進程的工作目錄;在當前特定目錄下工作的一個進程,默認自己的進程在哪個目錄下,這個目錄就是這個進程的當前目錄,創建文件/搜索文件都是在這個當前目錄下完成的

三:用getpid(),getppid()獲取該進程的PID,PPID

1.創建一個進程,就要操作系統創建對應的PCB,在Linux中稱為task_struct結構體對象,當存在多個時,就要用雙向鏈表方式進行連接管理,通過找到頭結點來訪問各個進程,為了區分這些進程,操作系統就分配了對應的PID,對應的PID是存在于task_struct結構體當中

2.進程在運行時,都會有獨屬于自己的PID,對于PID當每個進程在系統運行期間終止了后再啟動,操作系統分配的PID標識符多數情況下是會改變的

注:這里檢索指令也可以寫為 ps axj | head -1 && ps axj | grep test?

當grep自己過濾時,也要變為一個進程,而grep命名的進程中也含有關鍵字test,所以當它在執行過濾系統當中的進程時,首先得把grep變為一個進程,然后被cpu調度執行過濾代碼,在過濾時也就會把自己帶上,所以所有指令運行時都是進程

ps axj | head -1 ; ps ajx | grep test | grep -v grep? ? ? ?這樣的話就不會帶自己了

3.ps指令的本質:遍歷鏈表,在task_struct中將對應屬性格式化打印出來

4.kill -9 進程PID? 殺掉進程?

5.PID存在于task_struct結構體當中,這個結構體是屬于操作系統所維護的,是系統內的數據,所以用戶不能直接通過task_struct結構體對象以.的方式訪問PID,而是要通過對應的系統調用接口來獲取進程的PID,對于PPID也是如此

6.當每次重新登錄時,系統會為我們單獨創建一個bash進程,即創建一個命令行解釋的進程,在顯示器中打印出對應的對話框終端?

7.當運行一個進程時,命令行解釋器會將后面的指令變為bash的子進程,由子進程執行對應的命令,當子進程出現問題時,不影響bash進程,即在命令行中輸入的所有指令都是bash進程的子進程,bash進程只負責命令行解釋

四:用fork()來創建子進程

fork()是用來創建一個子進程,創建成功的話,給父進程返回子進程的PID,給自己返回0;失敗的話,給自己返回-1?

?

這里我們會發現fork()之后的代碼執行了兩次,即fork()之后會變成兩個進程,執行不同的代碼塊?

?1.為什么fork要給子進程返回0,給父進程返回子進程的PID?

返回不同的返回值,是為了區分不同的執行流,執行不同的代碼塊

給父進程返回子進程的PID,是為了通過父進程的PID去明確控制訪問的是哪個子進程(控制并區分子進程),PID也是用來標定子進程的唯一性的

而子進程只需要調用getpid()就能獲取進程的PID/PPID,所以找到父進程很容易,只需要返回0來標識成功即可

2.fork()函數究竟干了什么?

? ? ?當執行到fork()時,就要創建對應的子進程,而進程=內核task_struct數據結構對象+對應的代碼和數據,而創建對應的task_struct結構體對象是以原先老進程的task_struct為模板拷貝一份并用父進程的相應字段來初始化子進程,做相應修改,但對于代碼是沒有的,所以只能共享父進程的代碼;而對于數據,如果子進程也把對應的和父進程共享的數據拷貝一份的話,由操作系統自動完成,但這樣必然會造成子進程對這部分數據只修改一部分或者不修改,造成有兩份相同的數據形成冗余,占有資源,因此當子進程要訪問父進程的某一部分數據,并且操作系統識別到要對父進程的這部分數據做修改時,這時就在系統的內存位置重新開辟一塊空間將數據拷貝過去,寫入。這樣對于子進程想對父進程修改的數據,就再開辟空間,在新空間寫入==>父子進程間數據層面的寫時拷貝

?

對于fork本質上是一個函數,也是一個系統調用,在操作系統當中是有實現的?

所以這樣同一個函數就返回了兩次

3.一個變量是怎么會有不同的內容的?

?

五:操作系統學科的進程狀態?

1.cpu負責把一個進程放到cpu中去執行,由調度器決定被調度的具體進程,所有進程參與到操作系統的調度過程,所有的進程之間對于cpu資源本質是一種競爭關系,所以存在調度器是為了保證進程間的公平調度

2.為合理調度,每個cpu都要維護一個runqueue的結構體,cpu以運行隊列的形式對進程進行調度

?

3.對于每個進程都有時間片的概念,在時間片的時間中被cpu調度執行,時間結束,自動切換到下一個進程,如果這個進程還需要被調度執行的話,就會被鏈接到隊列最后面排隊等待調度執行

4.在一個時間段內,所有進程的代碼都會被調度執行------->并發執行

把進程放到cpu上去執行,再拿下來--------->進程切換

?

5.對于底層的硬件設備也可以采用先組織,再描述的方式進行管理,即每個外設都維護一個對應的結構體對象。這樣操作系統對于底層設備的管理也就轉換為在系統當中對某種設備結構體的管理,如果當前要訪問的資源不存在/未準備好,此時進程卡住了,這就是阻塞狀態

此時該進程 就在對應外設的等待隊列中排隊等待資源就緒,一旦資源就緒就可以鏈接到運行隊列中等待被cpu調度執行

6.當進程資源不足時,操作系統會將進程的代碼和數據置換到外設當中,這樣數據和代碼并未在內存當中,這時所處的狀態就是掛起狀態

?六:Linux中的進程狀態

1.Linux內核中的定義

"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

2.?R運行狀態(running): 并不意味著進程一定在運行中,它表明進程要么是在運行中要么在運行隊列里

當無IO,純運行時,就會變為R狀態?

3.S睡眠狀態(sleeping): 意味著進程在等待事件完成(這里的睡眠有時候也叫做可中斷睡眠
(interruptible sleep)

這里當printf是要訪問顯示器?的,當死循環打印時,設備不是處于一個正寫入的狀態,進程有很大可能是一直在等待的,所以是S+而不是R+;對于這里有+的表示是在前臺執行的(當運行起來程序時,bash命令行解釋器對輸入的指令不再有反應),可以用ctrl+c終止進程,可以采用./test & 這樣就會變為S,變為后臺執行,此時就必須用kill -9 PID來終止進程

4.D磁盤休眠狀態(Disk sleep)有時候也叫不可中斷睡眠狀態(uninterruptible sleep),在這個狀態的進程通常會等待IO的結束

只要進程當前正在有寫入任務交給磁盤時,如果磁盤沒有辦法立馬響應的話,需要等待進程,這個進程就不能以S淺度睡眠的狀態去等待,必須把自己設為D狀態,D狀態進程任何人都不能殺掉,包括操作系統,這樣可以保證向磁盤中寫入數據時,數據不會丟失。當磁盤把數據寫完之后返回時,此時進程的狀態就由D轉變為R,供cpu調度執行

即進程在等待磁盤進行寫入時,此時進程所處狀態為D狀態,是不響應操作系統的任何請求的

5.T停止狀態(stopped): 可以通過發送 SIGSTOP 信號給進程來停止(T)進程。這個被暫停的進程可以通過發送 SIGCONT 信號讓進程繼續運行

kill -l 查看信號

kill -19 PID 讓當前進程停下? kill -18 PID 恢復當前進程由T變為R狀態

S狀態一定是在等待某種資源,而T狀態可能在等待某種資源/被其他進程控制?

6.X死亡狀態(dead):這個狀態只是一個返回狀態,你不會在任務列表里看到這個狀態

7.Z(zombie)-僵尸狀態

當一個進程死亡的時候,在死亡之時,并不會立即進入dead的狀態,而是先進入Z狀態

當一個進程退出時,它并不是退出之后立即將所有資源進行釋放,而是操作系統需要把當前進程退出之時的退出信息維持一段時間,當對應的父進程讀取到進城的信息,進程的資源才會被釋放,這段時間所處的狀態為Z狀態,即我們把這樣已經死掉的,但是當前需要由父進程來關心,此時進程所維持的狀態

進程一般退出的時候,如果父進程沒有主動收回子進程信息,子進程會讓自己一直處于Z狀態進程的相關資源尤其是task_struct結構體不能釋放,所以會一直占用資源而且不釋放,就會導致內存泄露,父進程是bash進程的子進程,退出時會被bash所回收

父子進程當父進程先退出,子進程的父進程會被改為1號進程(操作系統),即父進程是1號進程的子進程也叫做孤兒進程,該進程被操作系統所領養,為未來該進程退出時的釋放資源

僵死狀態(Zombies)是一個比較特殊的狀態。當進程退出并且父進程使用wait()系統調用,后面講沒有讀取到子進程退出的返回代碼時就會產生僵死(尸)進程

僵死進程會以終止狀態保持在進程表中,并且會一直在等待父進程讀取退出狀態代碼

只要子進程退出,父進程還在運行,但父進程沒有讀取子進程狀態,子進程進入Z狀態

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

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

相關文章

【區塊鏈+基礎設施】深證金融區塊鏈平臺 | FISCO BCOS應用案例

作為數據交換密集型行業,資本市場是區塊鏈創新應用的重要領域,區塊鏈技術可以有效解決諸多痛點問題。比 如,針對信息不對稱的問題,區塊鏈技術通過將整個企業的經營活動信息上鏈,有效降低盡調成本,為投融資決…

配置windows環境下獨立瀏覽器爬蟲方案【不依賴系統環境與chrome】

引言 由于部署瀏覽器爬蟲的機器瀏覽器版本不同,同時也不想因為部署了爬蟲導致影響系統瀏覽器數據,以及避免爬蟲過程中遇到的chrome與webdriver版本沖突。我決定將特定版本的chrome瀏覽器與webdriver下載到項目目錄內,同時chrome_driver在初始…

我使用 GPT-4o 幫我挑西瓜

在 5 月 15 日,OpenAI 旗下的大模型 GPT-4o 已經發布,那時網絡上已經傳開, 但很多小伙伴始終沒有看到 GPT-4o 的體驗選項。 在周五的時候,我組建的 ChatGPT 交流群的伙伴已經發現了 GPT-4o 這個選項了,是在沒有充值升…

NSSCTF-Web題目21(文件上傳-phar協議、RCE-空格繞過)

目錄 [NISACTF 2022]bingdundun~ 1、題目 2、知識點 3、思路 [FSCTF 2023]細狗2.0 4、題目 5、知識點 6、思路 [NISACTF 2022]bingdundun~ 1、題目 2、知識點 文件上傳,phar偽協議 3、思路 點擊upload,看看 這里提示我們可以上傳圖片或壓縮包&…

應對.Kastaneya勒索病毒:保護您的數據安全

導言: 隨著科技的發展,網絡安全問題也日益嚴峻。最近,一種名為.Kastaneya的勒索病毒開始在網絡上出現,對用戶的計算機和數據造成嚴重威脅。本文91數據恢復將介紹.Kastaneya勒索病毒的特點及其傳播方式,并提供一些有效…

Unity 解包工具(AssetStudio/UtinyRipper)

文章目錄 1.UtinyRipper2.AssetStudio 1.UtinyRipper 官方地址: https://github.com/mafaca/UtinyRipper/ 下載步驟: 2.AssetStudio 官方地址: https://github.com/Perfare/AssetStudio 下載步驟:

【HarmonyOS NEXT】鴻蒙多線程Sendable開發

非共享模塊在同一線程內只加載一次,在不同線程間會加載多次,單例類也會創建多次,導致數據不共享,在不同的線程內都會產生新的模塊對象。 基礎概念 Sendable協議 Sendable協議定義了ArkTS的可共享對象體系及其規格約束。符合Sen…

STM32mp157aaa按鍵中斷實驗

效果圖&#xff1a; 源碼&#xff1a; #include "key.h" void hal_key1_rcc_gpio_init() {// 使能GPIOF組RCC->MP_AHB4ENSETR | (0x1 << 5);// 設置引腳位輸入模式GPIOF->MODER & (~(0X3 << 18));GPIOF->MODER & (~(0X3 << 16))…

[C++11] 退出清理函數(quick_exit at_quick_exit)

說明&#xff1a;在C11中&#xff0c;quick_exit和at_quick_exit是新增的快速退出功能&#xff0c;用于在程序終止時提供一種快速清理資源的方式。 quick_exit std::quick_exit函數允許程序快速退出&#xff0c;并且可以傳遞一個退出狀態碼給操作系統。與std::exit相比&#…

[今日一水]論壇該如何選擇

想要搭建一個論壇其實選擇是很多的&#xff0c;就比如國內的dz&#xff0c;國外的xenforo和flarum&#xff0c;具體還是根據的面向的用戶和需求來&#xff0c;就比如flarum它的界面肯定是三個論壇里最現代化的&#xff0c;但是xenforo社區生態很強&#xff0c;而dz對于國內用戶…

VMware創建新虛擬機教程(保姆級別)

&#x1f4e2; 續上一篇 最新超詳細VMware虛擬機安裝完整教程-CSDN博客 &#xff0c;本章將詳細講解VMware創建虛擬機。 一、創建新的虛擬機 點擊【創建新的虛擬機】&#xff01; 點擊【自定義&#xff08;高級&#xff09;】> 下一步&#xff01; > 默認下一步&#x…

耐克:老大的煩惱

股價暴跌20%&#xff0c;老大最近比較煩。 今天說說全球&#xff08;最&#xff09;大運動品牌——耐克。 最近耐克發布2023-2024財年業績&#xff08;截止于2024.5.31&#xff09;&#xff0c;還是爆賺幾百億美元&#xff0c;還是行業第一&#xff0c;但業績不及預期&#xf…

Redis為什么設計多個數據庫

?關于Redis的知識前面已經介紹過很多了,但有個點沒有講,那就是一個Redis的實例并不是只有一個數據庫,一般情況下,默認是Databases 0。 一 內部結構 設計如下: Redis 的源碼中定義了 redisDb 結構體來表示單個數據庫。這個結構有若干重要字段,比如: dict:該字段存儲了…

backbone是什么?

在深度學習中&#xff0c;特別是計算機視覺領域&#xff0c;"backbone"&#xff08;骨干網絡&#xff09;是指用于提取特征的基礎網絡。它通常是卷積神經網絡&#xff08;CNN&#xff09;&#xff0c;其任務是從輸入圖像中提取高層次特征&#xff0c;這些特征然后被用…

【第12章】MyBatis-Plus條件構造器(下)

文章目錄 前言一、使用 TypeHandler二、使用提示三、Wrappers四、線程安全性五、使用 Wrapper 自定義 SQL1.注意事項2.示例3. 使用方法 總結 前言 本章繼續上章條件構造器相關內容。 一、使用 TypeHandler 在 wrapper 中使用 typeHandler 需要特殊處理利用 formatSqlMaybeWit…

scikit-learn教程

scikit-learn&#xff08;通常簡稱為sklearn&#xff09;是Python中最受歡迎的機器學習庫之一&#xff0c;它提供了各種監督和非監督學習算法的實現。下面是一個基本的教程&#xff0c;涵蓋如何使用sklearn進行數據預處理、模型訓練和評估。 1. 安裝和導入包 首先確保安裝了…

【漏洞復現】D-Link NAS 未授權RCE漏洞(CVE-2024-3273)

0x01 產品簡介 D-Link 網絡存儲 (NAS)是中國友訊&#xff08;D-link&#xff09;公司的一款統一服務路由器。 0x02 漏洞概述 D-Link NAS nas_sharing.cgi接口存在命令執行漏洞&#xff0c;該漏洞存在于“/cgi-bin/nas_sharing.cgi”腳本中&#xff0c;影響其 HTTP GET 請求處…

類和對象-友元-全局函數做友元

全局函數做友元 #include<iostream> using namespace std;class Building {//goodGay全局函數是Building好朋友&#xff0c;可以訪問Building的私有成員 friend void goodGay(Building *building); public:Building(){m_SittingRoom "客廳";m_BedRoom &qu…

MyBatis學習筆記-數據脫敏

如果項目需要對一些特殊、敏感的數據進行脫敏處理。根據實際的需求可以考慮在讀寫的過程中分別做脫敏操作。 一、寫過程參數脫敏 主要是使用mybatis框架提供的Interceptor實現。需要考慮不同類型的參數解析處理方式不同。 @Slf4j @AllArgsConstructor @Intercepts({@Signatu…

【vuejs】vue-router 之 addRoute 動態路由的應用總結

1. Vue Router 概述 Vue Router 是 Vue.js 官方的路由管理器&#xff0c;用于構建單頁面應用。它與 Vue.js 深度集成&#xff0c;讓開發者能夠輕松地構建具有復雜用戶界面的單頁面應用。Vue Router 允許你定義不同的路由&#xff0c;并通過 router-view 組件在應用中顯示匹配的…