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