Linux系统-进程概念
Linux進(jìn)程概念
- 零、前言
- 一、馮諾依曼體系結(jié)構(gòu)
- 二、操作系統(tǒng)
- 三、進(jìn)程
- 1、描述進(jìn)程-PCB
- 2、查看進(jìn)程
- 3、獲取進(jìn)程標(biāo)示符
- 4、創(chuàng)建進(jìn)程-fork()
- 5、進(jìn)程狀態(tài)
- 6、僵尸進(jìn)程
- 7、孤兒進(jìn)程
- 8、進(jìn)程優(yōu)先級(jí)
- 9、環(huán)境變量
- 1)測(cè)試PATH
- 2)測(cè)試HOME
- 3)如何獲取環(huán)境變量
- 4)命令行變量
零、前言
本章主要講解操作系統(tǒng)的一些基礎(chǔ)概念知識(shí),為進(jìn)程的學(xué)習(xí)做鋪墊
一、馮諾依曼體系結(jié)構(gòu)
- 概念:
馮諾依曼體系結(jié)構(gòu)規(guī)定了硬件上的數(shù)據(jù)流動(dòng),而大部分計(jì)算機(jī)都遵守馮諾依曼體系,如筆記本,服務(wù)器等
- 示圖:
- 計(jì)算機(jī)基本硬件組成:
輸入單元:包括鍵盤, 鼠標(biāo),掃描儀, 寫板等
中央處理器(CPU):含有運(yùn)算器和控制器等
輸出單元:顯示器,打印機(jī)等
存儲(chǔ)器:物理內(nèi)存
注:輸入單元和輸出單元統(tǒng)稱外設(shè)
- 工作原理:
執(zhí)行程序時(shí),輸入設(shè)備的數(shù)據(jù)先預(yù)加載到存儲(chǔ)器中,通過存儲(chǔ)器將數(shù)據(jù)交給cpu進(jìn)行處理,cpu再將得到的結(jié)果預(yù)寫入寫回存儲(chǔ)器,最后再由存儲(chǔ)器將結(jié)果刷新到輸出設(shè)備上
- 注意:
不考慮緩存情況CPU能且只能對(duì)內(nèi)存進(jìn)行讀寫,不能訪問外設(shè)(輸入或輸出設(shè)備)
外設(shè)(輸入或輸出設(shè)備)要輸入或者輸出數(shù)據(jù),也只能寫入內(nèi)存或者從內(nèi)存中讀取
所有設(shè)備都只能直接和內(nèi)存打交道
- 示例:登錄上qq開始和某位朋友聊天的數(shù)據(jù)的流動(dòng)過程
你的電腦:輸入設(shè)備鍵盤將數(shù)據(jù)寫到內(nèi)存,內(nèi)存再將數(shù)據(jù)給CPU,CPU得到結(jié)果再將數(shù)據(jù)寫入內(nèi)存,最后內(nèi)存將數(shù)據(jù)刷新到網(wǎng)卡
朋友的電腦:輸入設(shè)備網(wǎng)卡將數(shù)據(jù)寫到內(nèi)存,內(nèi)存再將數(shù)據(jù)給CPU,CPU得到結(jié)果再將數(shù)據(jù)寫入內(nèi)存,最后內(nèi)存將數(shù)據(jù)刷新到顯示器上
- 為什么運(yùn)行程序必須先加載到內(nèi)存:
這是即是馮諾依曼體系結(jié)構(gòu)規(guī)定的,也是由于存儲(chǔ)器分級(jí)的原因?qū)е碌?/p>
- 示圖:存儲(chǔ)器層次結(jié)構(gòu)
內(nèi)存比較便宜速度慢,CPU速度快但是貴,為了平衡速度與經(jīng)濟(jì)CPU一般不會(huì)太大,所以CPU不能直接存儲(chǔ)數(shù)據(jù)
對(duì)于外設(shè)的輸入輸出效率會(huì)更慢,如果直接和CPU溝通會(huì)導(dǎo)致整個(gè)程序變得遲緩,所以由內(nèi)存作為中間者和所有設(shè)備進(jìn)行直接溝通
二、操作系統(tǒng)
- 概念:
任何計(jì)算機(jī)系統(tǒng)都包含一個(gè)基本的程序集合,稱為操作系統(tǒng)(OS)
- 操作系統(tǒng)包括:
內(nèi)核(進(jìn)程管理,內(nèi)存管理,文件管理,驅(qū)動(dòng)管理)
其他程序(例如函數(shù)庫(kù), shell程序等等)
- 設(shè)計(jì)OS的目的:
與硬件交互,管理所有的軟硬件資源
為用戶程序(應(yīng)用程序)提供一個(gè)良好的執(zhí)行環(huán)境
注:OS需要保護(hù)系統(tǒng)軟硬件,所以它對(duì)任何用戶都不信任,需要通過OS才能訪問系統(tǒng)軟硬件
- 定位:
操作系統(tǒng)也被稱作進(jìn)行軟硬件資源管理的軟件
- 如何理解 “管理”:
操作系統(tǒng)作為管理者,主要做事情決策
而操作系統(tǒng)之下的驅(qū)動(dòng)作為執(zhí)行者,進(jìn)行執(zhí)行操作系統(tǒng)的決定
最后的底層硬件則是一個(gè)被管理的角色
- 示圖:
- 怎么進(jìn)行管理:
描述:先對(duì)被管理者進(jìn)行描述,將其屬性數(shù)據(jù)獲取(數(shù)據(jù)寫到struct結(jié)構(gòu)體中)
組織:用鏈表或其他高效的數(shù)據(jù)結(jié)構(gòu)進(jìn)行管理數(shù)據(jù)(結(jié)構(gòu)體),也就是對(duì)數(shù)據(jù)的操作達(dá)到管理的效果
- 系統(tǒng)調(diào)用和庫(kù)函數(shù)概念:
在開發(fā)角度,操作系統(tǒng)對(duì)外會(huì)表現(xiàn)為一個(gè)整體,但是會(huì)暴露自己的部分接口,供上層開發(fā)使用,這部分由操作系統(tǒng)提供的接口,叫做系統(tǒng)調(diào)用
系統(tǒng)調(diào)用在使用上功能比較基礎(chǔ),但對(duì)用戶的要求相對(duì)也比較高,所以開發(fā)者對(duì)部分系統(tǒng)調(diào)用進(jìn)行適度封裝,從而形成庫(kù),利于更上層用戶或者開發(fā)者進(jìn)行二次開發(fā)
三、進(jìn)程
- 概念:
進(jìn)程是程序的一個(gè)執(zhí)行實(shí)例,從內(nèi)核的角度上看進(jìn)程是擔(dān)當(dāng)分配系統(tǒng)資源(CPU時(shí)間,內(nèi)存)的實(shí)體
即進(jìn)程=程序+內(nèi)核的PCB
1、描述進(jìn)程-PCB
- 概念:
進(jìn)程信息被放在一個(gè)叫做進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中,可以理解為進(jìn)程屬性的集合;在Linux中描述進(jìn)程的結(jié)構(gòu)體叫做task_struct
Linux操作系統(tǒng)下的PCB是: task_struct-PCB的一種,task_struct是Linux內(nèi)核的一種數(shù)據(jù)結(jié)構(gòu),它會(huì)被裝載到RAM(內(nèi)存)里并且包含著進(jìn)程的信息
- task_ struct內(nèi)容分類:
注:運(yùn)行在系統(tǒng)里的進(jìn)程都以task_struct鏈表的形式存在內(nèi)核里
2、查看進(jìn)程
- 示例:
- 示例:
3、獲取進(jìn)程標(biāo)示符
- 系統(tǒng)調(diào)用函數(shù):
使用getpid()系統(tǒng)調(diào)用函數(shù)獲取當(dāng)前進(jìn)程id(PID)
使用getppid()系統(tǒng)調(diào)用函數(shù)獲取當(dāng)前進(jìn)程的父進(jìn)程id(PPID)
注:getpid()和getppid()函數(shù)需要包含頭文件unistd.h
- 示例:
- 結(jié)果:
4、創(chuàng)建進(jìn)程-fork()
- fork()功能:
為當(dāng)前進(jìn)程創(chuàng)建子進(jìn)程,父子進(jìn)程代碼共享,數(shù)據(jù)各自開辟空間私有一份(采用寫時(shí)拷貝:進(jìn)行寫入時(shí)觸發(fā)拷貝)
- fork()返回值:
對(duì)于父進(jìn)程,如果創(chuàng)建成功返回子進(jìn)程的pid,否則返回負(fù)數(shù)
對(duì)于子進(jìn)程返回0(成功創(chuàng)建)
- 注意:
對(duì)子進(jìn)程返回0,是因?yàn)樽舆M(jìn)程只有一個(gè)父進(jìn)程,可以直接找到對(duì)應(yīng)父進(jìn)程
對(duì)父進(jìn)程返回子進(jìn)程pid的意義是可以在父進(jìn)程里直接得到子進(jìn)程ID(可能有多個(gè)子進(jìn)程),對(duì)某個(gè)子進(jìn)程進(jìn)行操作和管理
注:fork返回類型是pid_t,需要包含頭文件 sys/types.h
- 示例:
- 結(jié)果:
- 父子進(jìn)程分流執(zhí)行:
我們創(chuàng)建子進(jìn)程的意義是為了與父進(jìn)程進(jìn)行不同任務(wù),因?yàn)楦缸舆M(jìn)程的代碼共享,所以我們采用分支結(jié)構(gòu)進(jìn)行分流執(zhí)行程序
- 示例:
- 結(jié)果:
- 為什么ret有兩個(gè)返回值:
fork()函數(shù)在return的前一刻,其主體任務(wù)全部完成,也就是子進(jìn)程成功創(chuàng)建,此時(shí)父子進(jìn)程代碼共享,數(shù)據(jù)各有一份(寫時(shí)拷貝),在返回時(shí)發(fā)生寫實(shí)拷貝,對(duì)于父進(jìn)程的ret則是返回的子進(jìn)程的pid,對(duì)于子進(jìn)程的ret則是返回的0
5、進(jìn)程狀態(tài)
進(jìn)程有不同狀態(tài),一個(gè)進(jìn)程可以有幾個(gè)狀態(tài)
注:在Linux內(nèi)核里,進(jìn)程有時(shí)候也叫做任務(wù)
- 狀態(tài)在kernel源代碼里定義 :
- 解釋:
R運(yùn)行狀態(tài)(running):并不意味著進(jìn)程一定在運(yùn)行中,它表明進(jìn)程要么是在運(yùn)行中要么在運(yùn)行隊(duì)列里(可以被調(diào)度)
S睡眠狀態(tài)(sleeping):意味著進(jìn)程在等待事件完成(這里的睡眠有時(shí)候也叫做可中斷睡眠,即淺睡眠)
D磁盤休眠狀態(tài)(Disk sleep):有時(shí)候也叫不可中斷睡眠狀態(tài),在這個(gè)狀態(tài)的進(jìn)程通常會(huì)等待IO的結(jié)束(不能被進(jìn)程殺死,此外還包括僵尸進(jìn)程)
T停止?fàn)顟B(tài)(stopped):可以通過發(fā)送 SIGSTOP 信號(hào)給進(jìn)程來停止(T)進(jìn)程,這個(gè)被暫停的進(jìn)程可以通過發(fā)送 SIGCONT 信號(hào)讓進(jìn)程繼續(xù)運(yùn)行
X死亡狀態(tài)(dead):這個(gè)狀態(tài)只是一個(gè)返回狀態(tài),你不會(huì)在任務(wù)列表里看到這個(gè)狀態(tài)(非常快結(jié)束)
t (tracing stop)狀態(tài):表示進(jìn)程追蹤狀態(tài),即進(jìn)程在調(diào)試中停下來的一個(gè)狀態(tài)(有些內(nèi)核版本沒有該狀態(tài))
- 示圖:
- 查看狀態(tài)指令基本格式及選項(xiàng):
- 效果:
6、僵尸進(jìn)程
- 概念:
僵死狀態(tài)(Zombies)是一個(gè)比較特殊的狀態(tài)。當(dāng)進(jìn)程退出并且父進(jìn)程(使用wait()系統(tǒng)調(diào)用)沒有讀取到子進(jìn)程退出的返回代碼時(shí)就會(huì)產(chǎn)生僵死(尸)進(jìn)程
僵死進(jìn)程會(huì)以終止?fàn)顟B(tài)保持在進(jìn)程表中,并且會(huì)一直在等待父進(jìn)程讀取退出狀態(tài)代碼
即只要子進(jìn)程退出,父進(jìn)程還在運(yùn)行,但父進(jìn)程沒有讀取子進(jìn)程狀態(tài),子進(jìn)程進(jìn)入Z狀態(tài)
- 示例:
- 結(jié)果:
- 為什么有僵尸進(jìn)程:
創(chuàng)建進(jìn)程是用來執(zhí)行任務(wù)的,而進(jìn)程的退出狀態(tài)保存了任務(wù)執(zhí)行的狀態(tài)信息,所以必須被維持下,以此等待父進(jìn)程獲取其退出信息及任務(wù)狀態(tài),進(jìn)行下一步打算
- 僵尸進(jìn)程的危害:
父進(jìn)程如果一直不讀取,那子進(jìn)程就一直處于Z狀態(tài),而維護(hù)退出狀態(tài)本身就是要用數(shù)據(jù)維護(hù),也屬于進(jìn)程基本信息,所以保存在task_struct(PCB)中,即一直不回收僵尸進(jìn)程可能造成內(nèi)存資源的浪費(fèi),直到被回收后才能釋放其空間
7、孤兒進(jìn)程
- 概念:
父進(jìn)程先退出,子進(jìn)程就稱之為“孤兒進(jìn)程”,而孤兒進(jìn)程會(huì)被1號(hào) init 進(jìn)程(系統(tǒng))領(lǐng)養(yǎng),最后由 init 進(jìn)程回收
- 示例:
- 結(jié)果:
8、進(jìn)程優(yōu)先級(jí)
- 概念:
cpu資源分配的先后順序,就是指進(jìn)程的優(yōu)先權(quán)(priority),優(yōu)先權(quán)高的進(jìn)程有優(yōu)先執(zhí)行權(quán)利
配置進(jìn)程優(yōu)先權(quán)對(duì)多任務(wù)環(huán)境的linux很有用,可以改善系統(tǒng)性能
還可以把進(jìn)程運(yùn)行到指定的CPU上,以此可以大大改善系統(tǒng)整體性能
- 權(quán)限和優(yōu)先級(jí)的區(qū)別:
- 查看優(yōu)先級(jí):
使用 ps –l 命令
- 示例:
- 解釋:
UID : 代表執(zhí)行者的身份
PID : 代表這個(gè)進(jìn)程的代號(hào)
PPID :代表這個(gè)進(jìn)程是由哪個(gè)進(jìn)程發(fā)展衍生而來的,亦即父進(jìn)程的代號(hào)
PRI :代表這個(gè)進(jìn)程可被執(zhí)行的優(yōu)先級(jí),其值越小越早被執(zhí)行
NI :代表這個(gè)進(jìn)程的nice值
- PRI and NI:
PRI即進(jìn)程的優(yōu)先級(jí),或者通俗點(diǎn)說就是程序被CPU執(zhí)行的先后順序,此值越小進(jìn)程的優(yōu)先級(jí)別越高
NI即nice值,其表示進(jìn)程可被執(zhí)行的優(yōu)先級(jí)的修正數(shù)值
所以最終的優(yōu)先級(jí):PRI(new)=PRI(old)+nice
注:這里的PRI(old)可以理解為一直是基準(zhǔn)值80
當(dāng)nice值為負(fù)值的時(shí)候,那么該程序?qū)?huì)優(yōu)先級(jí)值將變小,即其優(yōu)先級(jí)會(huì)變高,則其越快被執(zhí)行
所以調(diào)整進(jìn)程優(yōu)先級(jí),在Linux下就是調(diào)整進(jìn)程nice值
nice其取值范圍是 -20至19 一共40個(gè)級(jí)別
- PRI vs NI:
進(jìn)程的nice值不是進(jìn)程的優(yōu)先級(jí),但是進(jìn)程nice值會(huì)影響到進(jìn)程的優(yōu)先級(jí)變化
可以理解nice值是進(jìn)程優(yōu)先級(jí)的修正修正數(shù)據(jù)
- 修改nice值:
先使用top命令,進(jìn)入top后按“r”–>輸入進(jìn)程PID–>輸入nice值
- 示例:
- 為什么PRI要有基準(zhǔn)值以及NI具有范圍:
避免過高或者過低的優(yōu)先級(jí)出現(xiàn),保證可控并且競(jìng)爭(zhēng)的相對(duì)公平,提高效率
便于運(yùn)算,不用再讀取優(yōu)先級(jí)信息,并且實(shí)現(xiàn)簡(jiǎn)單
- 進(jìn)程退出CPU的可能:
優(yōu)先級(jí)更高的進(jìn)程搶占了CPU
該進(jìn)程時(shí)間片到了(多進(jìn)程運(yùn)行)
注:進(jìn)程讓出或者占領(lǐng)CPU資源時(shí),就需要進(jìn)行保存或者恢復(fù)進(jìn)程的上下文數(shù)據(jù)
- 其他概念:
競(jìng)爭(zhēng)性: 系統(tǒng)進(jìn)程數(shù)目眾多,而CPU資源只有少量,甚至1個(gè),所以進(jìn)程之間是具有競(jìng)爭(zhēng)屬性的。為了高效完成任務(wù),更合理競(jìng)爭(zhēng)相關(guān)資源,便具有了優(yōu)先級(jí)
獨(dú)立性: 多進(jìn)程運(yùn)行,需要獨(dú)享各種資源,多進(jìn)程運(yùn)行期間互不干擾
并行: 多個(gè)進(jìn)程在多個(gè)CPU下分別,同時(shí)進(jìn)行運(yùn)行,這稱之為并行
并發(fā): 多個(gè)進(jìn)程在一個(gè)CPU下采用進(jìn)程切換的方式,在一段時(shí)間之內(nèi),讓多個(gè)進(jìn)程都得以推進(jìn),稱之為并發(fā)
9、環(huán)境變量
- 概念:
環(huán)境變量(environment variables)一般是指在操作系統(tǒng)中用來指定操作系統(tǒng)運(yùn)行環(huán)境的一些參數(shù)
環(huán)境變量通常具有某些特殊用途,還有在系統(tǒng)當(dāng)中通常具有全局特性(可以被子進(jìn)程繼承)
- 示例:
我們?cè)诰帉慍/C++代碼的時(shí)候,在鏈接的時(shí)候,從來不知道我們的所鏈接的動(dòng)態(tài)靜態(tài)庫(kù)在哪里,但是照樣可以鏈接成功,生成可執(zhí)行程序,原因就是有相關(guān)環(huán)境變量幫助編譯器進(jìn)行查找
- 常見環(huán)境變量:
PATH : 指定命令的搜索路徑
HOME : 指定用戶的主工作目錄(即用戶登陸到Linux系統(tǒng)中時(shí),默認(rèn)的目錄)
SHELL : 當(dāng)前Shell,它的值通常是/bin/bash
- 查看環(huán)境變量:
echo $NAME //NAME:你的環(huán)境變量名稱
- 示例:
1)測(cè)試PATH
注:以PATH為例,展現(xiàn)環(huán)境變量的作用
- 示例:簡(jiǎn)單寫個(gè)程序
- 結(jié)果:
- 引入:
為什么有些指令可以直接執(zhí)行,不需要帶路徑,而我們的二進(jìn)制程序需要帶路徑才能執(zhí)行?
- 原因:
執(zhí)行程序前,系統(tǒng)會(huì)在特定路徑下查找對(duì)應(yīng)程序
而PATH的作用是輔助系統(tǒng)進(jìn)程指令查找,PATH變量?jī)?chǔ)存的就是可能存在指令或者程序的路徑
- 示圖:
注:其實(shí)程序,命令,指令,可執(zhí)行程序等等都是一個(gè)概念
- 如何將程序像指令一樣執(zhí)行(不帶路徑執(zhí)行):
使用指令 export PATH=$PATH:path(程序所在路徑)
- 示例:
注:該添加方法只在當(dāng)前有用,退出Linux后則會(huì)恢復(fù),想永久設(shè)置則需在環(huán)境變量文件中進(jìn)行添加
- 示例:
2)測(cè)試HOME
- 對(duì)比效果:root和普通用戶執(zhí)行 echo $HOME
- 解釋:
一個(gè)用戶默認(rèn)所處的路徑是由環(huán)境變量HOME決定的,環(huán)境變量home是決定用戶所處的主工作目錄的
- 和環(huán)境變量相關(guān)的命令:
echo: 顯示某個(gè)環(huán)境變量值
export: 設(shè)置一個(gè)新的環(huán)境變量
env: 顯示所有環(huán)境變量
unset: 清除環(huán)境變量
set: 顯示本地定義的shell變量和環(huán)境變量
- 環(huán)境變量的組織方式:
- 解釋:
每個(gè)程序都會(huì)收到一張環(huán)境表,環(huán)境表是一個(gè)字符指針數(shù)組,每個(gè)指針指向一個(gè)以’\0’結(jié)尾的環(huán)境字符串
3)如何獲取環(huán)境變量
- 示例:
- 結(jié)果:
- 示例:
- 注意:
libc中定義的全局變量environ指向環(huán)境變量表,environ沒有包含在任何頭文件中,所以在使用時(shí)要用extern聲明
- 示例:
- 結(jié)果:
注:常用getenv和putenv函數(shù)來訪問特定的環(huán)境變量
4)命令行變量
- 在命令行中,我們可以定義兩種變量:
? 注:在命令行運(yùn)行的指令,它的父進(jìn)程都是bash
- 示例:
總結(jié)
以上是生活随笔為你收集整理的Linux系统-进程概念的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue之$nextTick属性
- 下一篇: Linux shell重复执行某命令n次