LINUX基礎 [二] - 進程概念

目錄

前言

什么是進程

如何管理進程

描述進程

組織進程

如何查看進程

通過 ps 命令查看進程?

通過 ls / proc 命令查看進程

通過系統調用 獲取進程標示符


前言

在學習了【Linux系統編程】中的 ??操作系統???馮·諾依曼體系結構??之后,我們已經對系統應該有了不錯的了解,接下里我們將繼續深入的了解操作系統最重要的的功能之一:進程

什么是進程

首先我們來看一個問題:

操作系統能不能一次運行多個程序呢?

答案是當然可以的!!因為運行的程序有很多,所以 OS 需要將這些運行的程序管理起來。
我們將這些正在運行的程序稱之為進程。(注意:是正在運行的程序叫進程,而不是程序本身)

【課本概念】:程序的一個執行實例,正在執行的程序等

【內核觀點】:擔當分配系統資源(CPU時間,內存)的實體

對于課本中的觀點大家可能會覺得難以理解,為何正在執行的程序就是一個進程呢。我們可以在Windows下按[Ctrl + shift?+ ESC]打開任務管理器查看一下:

這也就表明了在一個操作系統中不僅只能運行一個進程,還可以運行多個進程?

但是呢,進程不僅僅可以像上面這樣去理解。我們來思考一個問題

程序是文件嗎?

相信讀者肯定很清楚,文件是存放在磁盤中的,磁盤呢則是屬于外設。這一塊我們在 馮·諾依曼體系結構?有講得很清楚,對于CPU來說,它是只會和內存打交到的,所以磁盤中的數據需要先加載到內存中才可以被執行

那么,當可執行文件被加載到內存中時,該程序就成為了一個【進程】

總結:進程 = 程序(代碼 + 數據) + 內核申請的與該進程對應的數據結構(PCB)

如何管理進程

你說正在運行的程序叫做進程,那進程可以同時進行嗎?

  • 我們可以發現當你在聽網易云的時候你也可以登錄微信聊天,也可以刷抖音 所以進程是可以同時進行的。是因為操作系統把這些進程給管理起來了。也就是先描述再組織
  • 操作系統會創建一個描述和控制該進程的結構體。這個結構體稱之為進程控制塊(PCB,Processing Control Block),里面包含了該進程幾乎所有的屬性信息,同時通過進程控制塊也可以找到該進程的代碼和數據。
  • 在 Linux 中,進程控制塊就是 struct task_struct 結構體。
  • 描述好所有進程了,還需要將所有進程的 PCB 給組織起來(通過雙鏈表的方式),此時操作系統只需要拿到雙鏈表的頭指針,就可以找到所有進程的 PCB。
  • OS 把對進程的管理就轉換成了,對數據結構中 PCB 的管理,即對雙鏈表的增刪查改操作。

假設這里有一個可執行程序?test它存儲在磁盤上就是一個普通文件,當我們?./test?運行此程序,操作系統會做以下事情:將該程序從磁盤加載到內存中,并為該程序創建對應的進程,申請進程控制塊(PCB)。?

描述進程

先思考:人是如何辨別事物或者對象的??

比如你在放學路上見到一個女生一見鐘情,于是你記住了他的樣貌,開始像別人打聽這個女生,因為你不認識這個女生,所以你會對他進行描述,比如說長得很漂亮、水靈的眼睛、瓜子臉……當你提供的特征越來越多的時候,認識她的人或許就能通過你的描述找到這個女生。而這個過程中,這個女生的各種特征其實就是他的屬性,所以我們可以得出一個結論:人是通過屬性去辨別事物和對象的,當屬性足夠多的時候,這一堆屬性的集合,就是目標對象!!

?

所以我們推斷出任何一個進程加載到內存時,OS需要創建一個描述進程的結構體對象——PCB(process ctrl block進程控制塊)?,而他的本質就是對進程屬性集合的描述!

  • 課本中的叫法是:PCB(Process Control Block)
  • Linux操作系統下的PCB是:task_struct

這個結構體呢就是組織了各種各樣的屬性,才可以去很好地描述一個進程

task_struct的內容:

標示符: 描述本進程的唯一標示符,用來區別其他進程。(有點類似學校里每個學生的學號,是一個唯一標識,方便我們通過標示符來管理進程)

狀態: 任務狀態,退出代碼,退出信號等。(OS中同時存在多個進程,所以可能有的進程正在運行、有的正在休眠、有的在正在待定、有的即將銷毀……也就是說每個進程當前可能都處于某一種狀態)

優先級: 相對于其他進程的優先級。(OS中有多個進程,所以先執行誰肯定是要有一個標準的,所以進程之間可能存在對應的優先級關系)

程序計數器: 程序中即將被執行的下一條指令的地址。(以前我們在學習函數棧幀的時候,我們知道代碼是從上往下運行的,但是這個過程中可能會遇到出現某個函數需要我們進行跳轉,這個時候當前的棧幀會暫時保存著,然后當跳轉過去的相關代碼執行結束后再返回之前棧幀的位置繼續運行。但是由于OS中不僅僅只有一個進程,所有有可能這個進程在執行的時候可能會被一些切換給中斷,轉而去執行別的進程,然后該進程可能會進入休眠模式,而后期我們可能還會去喚醒這個進程,這個時候由于之間的棧幀被銷毀了,所以已經不記得執行到哪句代碼了,因此程序計數器存在的意義就是幫助沒我們記住即將被執行的下一條指令的地址!舉個更好理解的例子就是,比方說你正在數一堆書,當你數到50的時候,這個時候突然一個電話告訴你外賣到了,為了不讓外賣員等太久,你需要暫停當前的工作馬上下去,但是你又怕你數過的數字忘記了,所以你就把他記在本子上,當你取完外賣后,你就可以通過從本子上的數字繼續往下數!)

內存指針: 包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針(我們一個可執行程序要運行還需要有對應的數據和代碼,所以PCB對象必然需要有一個指針指向這塊空間,當進程響應的時候能夠及時找到,另一方面可能會存在多種數據類型的指針,為了滿足不同場景下的需求——通過數據結構和算法)

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

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

記賬信息: 可能包括處理器時間總和,使用的時鐘數總和,時間限制,記賬號等。(可能會包含進程的一些運行時間,其實對進程的調度來說是有作用的,因為在多個進程的情況下,只有一個CPU,所以先將哪個進程放到CPU里其實是由調度器決定的,而調度器除了考慮進程狀態和一些優先級之外,他會盡可能秉持著公平的原則,比如說有盡可能地優先讓執行時間短的進程優先去調度。)

其他信息

轉換為代碼形式的話就可以是下面這樣

struct PCB{進程的編號進程的狀態進程的優先級...相關的指針信息
};

既然知道了如何去描述一個PCB結構體,我們就要來知道操作系統對一個進程總共會做哪些事情

  • 為該進程創建對應的PCB對象
  • 將該進程的代碼和數據加載到內存中

所以,很多教科書在介紹進程的時候只會說它在計算機內部是一個PCB對象,其實對于一個進程來說:應該是由操作系統為其創建出來的?PCB對象 + 其數據代碼?組成的

組織進程

我們知道?進程=內核PCB數據結構對象+你自己的代碼和數據。

  • 但是OS本質上是對PCB做管理,他并不關心你的代碼和數據因為他只要能找到PCB,就可以通過他里面的一個相關的指針去找到對應的代碼和數據,然后再交給CPU去運行!!
  • 舉個例子就比如HR對人才的管理本質上就是對簡歷進行管理,然后安排面試的時候再通過簡歷來找到你的相關信息。

但是PCB特別多,所以我們需要想辦法管理起來。

其實在我們的Linux中task_struct主要是以雙鏈表的形式組織起來。

??

?你可能會疑惑,使用一個順序表來存儲不是更好嗎??其實在OS內部對于進程的管理方式并沒有像我們以前學的數據結構那么純粹,他的場景會更加復雜,也就是說該進程可能會需要根據不同的需求被存儲在隊列中、雙鏈表中、二叉樹中、棧中……

所以將進程按照節點的方式鏈接起來其實會更方便我們將這個進程放在不同的數據結構中,然后我們可以通過對應的指針信息來講他們更好地管理起來。

舉個例子,比如說我在當前進程中有一個隊列指針。因為在OS中可能會有一些存儲進程指針的運行隊列和等待隊列,如果你想讓這個進程去哪個隊列,你就可以通過修改隊列指針的鏈接隊形做到,從而實現更加靈活的管理。?

所以對進程管理工作取決于你把他放入哪個正在被組織的數據結構中,因為不同的數據結構有不同的特點,所以背后對應的就是不同的算法,而不同的算法對應的就是不同的應用場景。

如何查看進程

現在我們明白了操作系統如何去描述并組織進程,接下去我們就切身地來看一看進程長什么樣吧

下面呢是我們要進行測試的代碼:

#include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <sys/types.h>5 int main()6 {7   // 死循環8   while(1)9   {10     pid_t id = getpid();11     //pid_t fid = getppid();12     //printf("I am a process! pid : %d, ppid : %d\n",id,fid);13     printf("I am a process! pid : %d\n",id);//程序停留一秒在輸出                                                                     14     sleep(1);15   }16 17   return 0;18  }

通過 ps 命令查看進程?

??

查看當前我們正在運行的進程

??

此時我們來查看以下當前運行程序的進程

ps ajx | head -1 && ps ajx | grep mytest
  • ?ps ajx?—— 查看當前系統中所有進程
  • head -1?—— 獲取第一行
  • grep mytest?—— 過濾只帶【mytest】的進程?

??

那有同學可能會問:為什么在過濾進程的時候會有 grep --color=auto mytest 這個東西呢?

grep在進行過濾的時候自己也要變成一個進程,也可以看到他們使用grep命令的時候也帶【mytest】關鍵字的,所以在過濾的時候把自己也過濾出來了。

這也側面證明了所有指令在運行的時候都是進程

但如果我們不想看到這個也是有辦法的,那就是在?grep?命令后面加個-v grep把其過濾掉即可

ps ajx | head -1 && ps ajx | grep mytest | grep -v grep

通過 ls / proc 命令查看進程

我們都清楚根目錄下有很多的路徑

注意上面的proc目錄,它是一個內存文件系統,里面放的是當前系統實時的進程信息。我們進入此目錄看看:

但是呢,上面這些呢是全部的進程,若我們只是想要查看某個進程的話就要根據其PID值去進行對應的查找。這個PID呢就是我們在上面在介紹task_struct這個Linux下的PCB結構體的時候所講到的【標識符】這個東西,它是?描述本進程的唯一標示符,用來區別其他進程

但是這么看不夠清晰,我們以列表的形式來進行查看。這里我們主要關注兩個:一個是cwd目錄,另一個則是exe

首先我們來看到的是這個【exe】,很明顯它是一個可執行文件,那就是我們在當前目錄下的mytest這個可執行文件
接下去的話就是這個【cwd】了,其意思為current work directory當前進程的工作目錄

接下來,我們來詳細說一這個??cwd

看以下的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(){printf("我的PID:%d\n",getpid()); FILE* fp = fopen("log.txt","w");                                                                                                                                if(fp==NULL){return 1;}fclose(fp);printf("新建文件完成\n");sleep(50);return 0;}

在當前的 proc.c 程序中,創建一個log.txt 的文件,創建好后,大家覺得這個文件會出現在哪里呢? 我們運行以下看看

我們發現在?proc.c ?程序中創建的 log.txt ?文件出現在當前目錄下,這是為什么呢?

我們來根據程序中的進程標識符來檢查一個這個進程

此時我們發現進程中的存有cwd---當前工作目錄,所以導致在此程序中創建的任何文件,在沒有指定放在哪里的時候,常見的文件會默認放在進程指定的cwd----當前工作目錄下

通過系統調用 獲取進程標示符

上面我們有講到了這個PID進程標示符,是通過ps這個命令來查看的,那我們能否直接獲取這個PID呢?

  • 在上面我們使用ps ajx查看到了當前進程所對應的?PID,但是呢這相當于是遍歷操作,如果我沒有加grep mytest的話出來的進程數就會很多了
  • 那現在我們所要做到的就是對一個單獨的進程去獲取其 PID,此時我們能想到的就是通過庫函數來實現。在之前的文章中我們又說到過對于操作系統而言它是不會相信任何人的,所以會提供給用戶一些系統調用(庫函數),那我們只需要通過這個系統調用即可獲取到當前進程的 PID 值

  • 那首先呢,我們先要去查詢一下這個getpid()怎么使用,那還是使用到我們的老朋友man
man 2 getpid

?進去之后看到,有兩個庫函數,那如果要使用這兩個庫函數的話就需要引入對應的頭文件

下面我給出一段命令,它可以實時監控當前系統的進程

while :;do ps ajx | head -1 && ps ajx | grep mytest | grep -v grep; echo "------------------------------------------------------------"; sleep 1; done; 
  • 然后就讓我們來觀察一下其是否真的可以獲取到當前進程的PID,首先運行上面的這段指令,我們看到了當前系統中并不存在有關mytest的進程,但是呢在我們把mytest這個可執行程序運行起來的時候,右側就突然就多出了一條進程的相關信息
  • 后一核對相關的PID值就發現確實是當前運行起來的這個進程

  • 但是呢當我在將當前這個進程給結束之后再去把它起起來的時候,就發現當前這個進程的PID值發生了變化

?其實的話,這個現象是很正常的每次重新啟動進程其 PID 值是會出現不同的情況

舉個很簡單的例子來說吧,小王在高考結束完后上了一所不是很理想的大學🏫,在開學前兩天時學習為其分配了對應的學號。但是呢小王卻并不滿意自己所待的這個學校,所以就退了學繼續參加高考,在又一次的高考結束后他還是被原來的這所學校給錄取。但是呢我們可以知道,即使你進了一個學校兩次,但是學號卻不一定是一樣的

這也就是為什么一個進程在啟動兩次后會出現不同PID值的原因

?剛才我們在通過【man】手冊查看getpid()這個函數的時候,還看到了getppid()這個函數,它是獲取當前進程的父進程的 PID

  • 這個PPID呢就在PID的左邊

下面是改進的測試代碼

printf("I am a process, my id is: %d, parent is: %d\n", getpid(), getppid());
  • 馬上來看一下是否真的可以獲取到

  • 接下去我們再來觀察一下現象:通過3次結束子進程,我們觀察到了子進程確實每次都會發生變化,但是呢對于父進程而言卻不會發生任何的變化,這是為什么呢?

  • 我們可以先去查看一下這個父進程到底是什么鬼…(((m -__-)m
ps ajx | head -1 && ps ajx | grep 18866

原因解析:
每次在登錄XShell的時候,系統會為我們單獨再創建一個Bash進程,即命令行解釋的進程,幫我們在顯示器中打印出對話框終端

[XAS@iZf8z3lh8un7rc5rk1ney3Z lesson13]$  -----  【父進程----ppid】

我們在命令行中輸入的所有指令都是Bash進程的子進程Bash進程只負責命令行的解釋,具體執行出問題的時候只會影響它的子進程

ls /proc/18866	-- 子進程【PID】

上面這樣解釋可能還是比較抽象,一樣來舉個例子

  • 還記得,我們在講解shell運行原理的時候曾經說到過王婆是一位資本家,她為了不損壞自己的名聲呢,在別人找她說媒的時候會派遣一些實習生去,即使實習生出了問題她的名譽也不會受到影響

?這就可以對照到父進程與多個子進程,可以有多個子進程在這個父進程上面運行,即使某一個子進程突然出問題終止了,還有其他子進程在運行,此時父進程也是有保障的,所以子進程每次都會發生變化,但是父進程永遠都不會變化

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

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

相關文章

什么是PHP偽協議

PHP偽協議是一種特殊的URL格式&#xff0c;允許開發者以不同于傳統文件路徑訪問和操作資源。以下是一些常見的PHP偽協議及其詳細介紹&#xff1a; 常見的PHP偽協議 1. **file://** - **用途**&#xff1a;訪問本地文件系統。 - **示例**&#xff1a;file:///path/to/file.txt。…

股指期貨貼水波動,影響哪些投資策略?

先來說說“貼水”。簡單來說&#xff0c;貼水就是股指期貨的價格比現貨價格低。比如&#xff0c;滬深300指數現在是4000點&#xff0c;但股指期貨合約的價格只有3950點&#xff0c;這就叫貼水。貼水的大小會影響很多投資策略的收益&#xff0c;接下來我們就來看看具體的影響。 …

算法·動態規劃·入門

動態規劃的概念 狀態&#xff1a;也就是DP數組的定義 狀態轉移 dp五部曲的理解 見&#xff1a;代碼隨想錄 優先確定&#xff1a;狀態的定義&#xff0c;狀態轉移的房產 根據狀態轉移方程確定&#xff1a;遍歷順序&#xff0c;初始化 狀態壓縮 本質上就是變量個數減少&am…

在刀刃上發力:如何精準把握計劃關鍵節點

關鍵路徑分析是項目管理中的一種重要方法&#xff0c;它通過在甘特圖中識別出項目中最長、最關鍵的路徑&#xff0c;來確定項目的最短完成時間。 關鍵路徑上的任務都是項目成功的關鍵因素&#xff0c;任何延誤都可能導致整個項目的延期。關鍵路徑分析對于項目管理者來說至關重要…

第二天 開始Unity Shader的學習之旅之熟悉頂點著色器和片元著色器

Shader初學者的學習筆記 第二天 開始Unity Shader的學習之旅之熟悉頂點著色器和片元著色器 文章目錄 Shader初學者的學習筆記前言一、頂點/片元著色器的基本結構① Shader "Unity Shaders Book/Chapter 5/ Simple Shader"② SubShader③ CGPROGRAM和ENDCG④ 指明頂點…

潯川社團官方聯合會維權成功

在2025.3.2日&#xff0c;我社團檢測文章侵權中&#xff0c;檢測出3篇文章疑似遭侵權&#xff0c;隨后&#xff0c;總社團聯合會立即聯系CSDN版權&#xff0c;經過17天的維權&#xff0c;至今日晚&#xff0c;我社團維權成功&#xff01;侵權文章全部被設置為轉載。 在此&…

介紹一個測試boostrap表格插件的好網站!

最近在開發一個物業管理系統。用到bootstrap的表格插件bootstrap table&#xff0c;官方地址&#xff1a; https://bootstrap-table.com/ 因為是英文界面&#xff0c;對國人不是很友好。后來發現了小書童網站 IT小書童 - 為程序員提供優質教程和文檔 網站&#xff1a; IT小…

釘釘機器人

準備 參考官方文檔 已經完成成為釘釘開發者流程。已經完成創建應用流程。已經完成添加應用能力流程 企業內部需要企業管理員開通權限&#xff0c;我自己創建了一個組織&#xff0c;用自己的組織創建機器人就方便很多&#xff0c;很多權限無需單獨去申請了。 創建機器人 進…

Androidstudio實現引導頁文字動畫

文章目錄 1. 功能需求2. 代碼實現過程1. 編寫布局文件2. 實現引導頁GuideActivity 3. 總結4. 效果演示5. 關于作者其它項目視頻教程介紹 1. 功能需求 1、引導頁具有兩行文字&#xff08;“疫情在前”和“共克時艱”&#xff09;&#xff0c;和向上的 圖標。 2、進入【引導頁】…

在線生成自定義二維碼

在線生成自定義二維碼 1. 引言 二維碼已成為現代互聯網的重要工具&#xff0c;廣泛應用于鏈接分享、支付、身份認證等場景。然而&#xff0c;很多在線二維碼生成工具功能有限&#xff0c;難以滿足個性化需求。如果你需要 自定義顏色、Logo、不同形狀的二維碼&#xff0c;那么…

藍橋杯 之 第27場月賽總結

文章目錄 習題1.抓豬拿國一2.藍橋字符3.藍橋大使4.拳頭對決 習題 比賽地址 1.抓豬拿國一 十分簡單的簽到題 print(sum(list(range(17))))2.藍橋字符 常見的字符匹配的問題&#xff0c;是一個二維dp的問題&#xff0c;轉化為對應的動態規劃求解 力扣的相似題目 可以關注靈神…

計算機的基本組合和工作原理

計算機的基本組成和工作原理可以概括為以下幾個核心部分&#xff1a; 一、計算機的基本組成&#xff08;馮諾依曼體系結構&#xff09; 現代計算機基于馮諾依曼體系結構&#xff0c;主要由以下五大部件組成&#xff1a; 控制器&#xff08;Control Unit, CU&#xff09; 功能&…

[思考記錄]兩則:宏觀視角、理想化

#宏觀視角# 昨天聽金老師講解了他初步整理的大模型宏觀概念關系圖&#xff0c;受益不少。圖上不僅是涵蓋了諸多概念&#xff0c;更厲害的應該在于把概念之間的關系進行了描述&#xff0c;更直觀展現了概念是如何與其他概念相互作用的。幫助從整體的角度去理解&#xff0c;以及透…

正則表達式:文本處理的瑞士軍刀

正則表達式&#xff1a;文本處理的瑞士軍刀 正則表達式&#xff08;Regular Expression&#xff0c;簡稱 Regex&#xff09;是一種用于匹配、查找和操作文本的強大工具。它通過定義一種特殊的字符串模式&#xff0c;可以快速地在文本中搜索、替換或提取符合特定規則的內容。正…

SQL 中UPDATE 和 DELETE 語句的深入理解與應用

在 SQL 中&#xff0c;UPDATE和DELETE語句是用于操作表數據的重要工具&#xff0c;它們允許我們對已存在的數據進行修改和刪除。 一、UPDATE 語句 &#xff08;一&#xff09;基本語法 UPDATE語句的基本語法如下&#xff1a; UPDATE table_name SET column1 value1, colum…

C 語 言 --- 掃 雷 游 戲(初 階 版)

C 語 言 --- 掃 雷 游 戲 初 階 版 代 碼 全 貌 與 功 能 介 紹掃雷游戲的功能說明游 戲 效 果 展 示游 戲 代 碼 詳 解game.htest.cgame.c 總結 &#x1f4bb;作 者 簡 介&#xff1a;曾 與 你 一 樣 迷 茫&#xff0c;現 以 經 驗 助 你 入 門 C 語 言 &#x1f4a1;個 人 主…

車載以太網網絡測試-21【傳輸層-DOIP協議-4】

目錄 1 摘要2 DoIP entity status request/response&#xff08;0x4001、0x4002&#xff09;2.1 使用場景2.2 報文結構2.2.1 0x4001&#xff1a;DoIP entity status request2.2.2 0x4002&#xff1a;DoIP entity status response 3 Diagnostic power mode information request/…

CH347使用筆記:CH347結合STM32CubeIDE實現單片機下載與調試

目錄 基于 STM32CubeIDE的 CH347 JTAG/SWD調試器使用說明1. CH347驅動安裝與配置2. STM32CubeIDE調試器配置2.1 打開相關工程后&#xff0c;進行以下操作2.2 openocd.exe替換2.3 腳本添加2.4 更改調試器選擇 3. 下載程序4. 使用過程中可能遇到的問題4.1 CH347未插入4.2 Openocd…

LVGL常用功能備忘

概述 本文選用LVGL 8.3版本 8.3版本實測幀率比起9版本高,多個GUI工具支持 相關鏈接 LVGL官網 https://lvgl.io/ LVGL 文檔 https://docs.lvgl.io/8.3/ LVGL倉庫 https://github.com/lvgl LVGL移植 獲取源碼 https://github.com/lvgl/lvgl/tree/release/v8.3 下載文件即可 文件…

k8s搭建kube-prometheus

后續再補一個k8s集群搭建的博客&#xff0c;從0開始搭建k8s集群。使用kube-prometheus非常方便&#xff0c;主要問題只在于拉取鏡像。除了拉取鏡像外其他時間5分鐘即可。耐心等待拉取鏡像。 一.kube-prometheus簡介 kube-prometheus 是一個專為 Kubernetes 設計的開源監控解決…