衡水企業(yè)網(wǎng)站巨量關(guān)鍵詞搜索查詢
個(gè)人主頁(yè)~
從硬件到軟件了解進(jìn)程
- 一、馮諾依曼體系結(jié)構(gòu)
- 二、操作系統(tǒng)
- 三、操作系統(tǒng)進(jìn)程管理
- 1、概念
- 2、PCB和task_struct
- 3、查看進(jìn)程
- 4、通過(guò)系統(tǒng)調(diào)用fork創(chuàng)建進(jìn)程
- (1)簡(jiǎn)述
- (2)系統(tǒng)調(diào)用生成子進(jìn)程的過(guò)程
- 〇提出問(wèn)題
- ①fork函數(shù)
- ②父子進(jìn)程關(guān)系
- ③解答問(wèn)題
一、馮諾依曼體系結(jié)構(gòu)
我們常見(jiàn)的嵌入式結(jié)構(gòu),包括哈佛結(jié)構(gòu)和馮諾依曼體系結(jié)構(gòu),我們所使用的計(jì)算機(jī)電腦就是馮諾依曼體系結(jié)構(gòu),下圖就是該體系的直觀圖
在這里的存儲(chǔ)器指的是內(nèi)存,如果不考慮緩存的情況,這里的CPU能且只能對(duì)內(nèi)存進(jìn)行讀寫(xiě),不能訪問(wèn)輸入輸出設(shè)備,輸入輸出設(shè)備要輸入輸出數(shù)據(jù)也只能寫(xiě)入內(nèi)存或者從內(nèi)存中讀取,就是說(shuō),雖然CPU是中央處理器,但對(duì)于馮諾依曼結(jié)構(gòu)來(lái)說(shuō),內(nèi)存才是中心的部件,所有數(shù)據(jù)必須先經(jīng)過(guò)內(nèi)存然后再流向別處
馮諾依曼體系結(jié)構(gòu)是計(jì)算機(jī)設(shè)備得以普及的重大突破,我們知道計(jì)算機(jī)的存儲(chǔ)速度如下圖,寄存器是最快的存儲(chǔ)也是最貴的,機(jī)械硬盤(pán)HDD是最慢的存儲(chǔ)也是最便宜的,如果沒(méi)有馮諾依曼結(jié)構(gòu),我們的計(jì)算機(jī)要不然就是便宜速度慢,要不就是昂貴速度快,馮諾依曼結(jié)構(gòu)的原理是,在CPU進(jìn)行計(jì)算的時(shí)候,內(nèi)存已經(jīng)接收外部輸入設(shè)備輸入的數(shù)據(jù)并存儲(chǔ),然后在CPU進(jìn)行完計(jì)算后將結(jié)果取出,然后將結(jié)果放到輸出設(shè)備,再把輸入的數(shù)據(jù)交給CPU進(jìn)行計(jì)算,這樣,低速的輸入輸出設(shè)備、中速的內(nèi)存以及高速的CPU有機(jī)整合,形成了現(xiàn)代計(jì)算機(jī)雛形
二、操作系統(tǒng)
任何計(jì)算機(jī)系統(tǒng)都包含一個(gè)基本的程序集合,它就被稱為操作系統(tǒng),我們前面說(shuō)過(guò),操作系統(tǒng)就是操作系統(tǒng)內(nèi)核+命令行解釋器(shell),設(shè)計(jì)操作系統(tǒng)的目的就是更好地與硬件交互,管理軟件資源,為應(yīng)用程序提供一個(gè)良好的執(zhí)行環(huán)境
如上圖所示,我們可以清楚看到對(duì)于用戶和系統(tǒng)軟件部分的交互,我們是不能直接調(diào)用操作系統(tǒng)的,操作系統(tǒng)像一只小蝸牛,它縮在殼里伸出觸角與你交流,除了觸角以外,你是碰不到蝸牛的身體的,你只能碰到殼,這里的觸角就是系統(tǒng)調(diào)用接口,而操作系統(tǒng)也有殼,除了調(diào)用系統(tǒng)調(diào)用接口,其他的方式都沒(méi)法間接使用操作系統(tǒng),因?yàn)橄到y(tǒng)調(diào)用在使用上操作比較基礎(chǔ),對(duì)用戶的要求比較高,所以開(kāi)發(fā)者就對(duì)部分系統(tǒng)調(diào)用進(jìn)行適度封裝,從而形成了庫(kù),有了庫(kù)我們程序員就可以更好的進(jìn)行開(kāi)發(fā)軟件,然后開(kāi)發(fā)出來(lái)的軟件再被普通人所使用
對(duì)于硬件部分和系統(tǒng)軟件部分的交互,我們前面提到了,操作系統(tǒng)是做管理的,何為管理呢?對(duì)于程序員而言,管理通過(guò)計(jì)算機(jī)語(yǔ)言的表示方法就是數(shù)據(jù)結(jié)構(gòu),大家不妨想一想,我們平常生活所遇到的有關(guān)于管理的問(wèn)題,是不是都可以轉(zhuǎn)化為數(shù)據(jù)結(jié)構(gòu)的方式來(lái)解決呢?我是一個(gè)學(xué)生,我來(lái)舉一個(gè)有關(guān)于學(xué)生管理例子:一個(gè)學(xué)校有十個(gè)學(xué)院,每個(gè)學(xué)院有一位院長(zhǎng)一百位學(xué)生,假設(shè)我們的學(xué)校就這么單調(diào),沒(méi)有其他類似輔導(dǎo)員這樣的職位,校長(zhǎng)是不直接管理我們的,校長(zhǎng)吩咐院長(zhǎng)來(lái)管理學(xué)生,院長(zhǎng)就要親力親為,親自來(lái)管理這些學(xué)生,學(xué)生的屬性都是不同的,但是學(xué)生屬性的類型都是相同的,他們都有名字、性別、年齡、家庭住址,把學(xué)生這個(gè)群體定義成一個(gè)struct結(jié)構(gòu)體,然后不同的學(xué)生填不同的數(shù)值,然后按照學(xué)號(hào)前后以單鏈表的方式連接起來(lái),這樣就把每個(gè)學(xué)院學(xué)生連接起來(lái)了,對(duì)學(xué)生的管理就是對(duì)鏈表的增刪查改,校長(zhǎng)想要對(duì)某個(gè)學(xué)生進(jìn)行管理就可以通過(guò)院長(zhǎng)執(zhí)行,這里的校長(zhǎng)就是操作系統(tǒng),院長(zhǎng)就是驅(qū)動(dòng)程序,而學(xué)生就是硬件資源,一個(gè)事件可以拆分為決策+執(zhí)行,操作系統(tǒng)負(fù)責(zé)決策,驅(qū)動(dòng)程序負(fù)責(zé)執(zhí)行,我們剛才的例子對(duì)于學(xué)生也就是硬件資源就是一個(gè)先描述再組織的過(guò)程,先將個(gè)體描述出來(lái),再將個(gè)體組織起來(lái)
三、操作系統(tǒng)進(jìn)程管理
1、概念
進(jìn)程是正在執(zhí)行的程序的實(shí)例,是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,它包含了程序計(jì)數(shù)器、寄存器、內(nèi)存空間、打開(kāi)的文件描述符等運(yùn)行上下文信息,這些信息共同構(gòu)成了進(jìn)程執(zhí)行的環(huán)境
進(jìn)程是正在執(zhí)行的程序的實(shí)例,程序本身只是存儲(chǔ)在磁盤(pán)等介質(zhì)上的一組指令和數(shù)據(jù)的集合,是靜態(tài)的,只有當(dāng)程序被加載到內(nèi)存中,并由操作系統(tǒng)為其分配資源、創(chuàng)建相應(yīng)的數(shù)據(jù)結(jié)構(gòu)來(lái)管理其執(zhí)行時(shí),它才成為一個(gè)進(jìn)程,即變成了一個(gè)動(dòng)態(tài)的執(zhí)行實(shí)體
進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的基本單位,操作系統(tǒng)需要為每個(gè)進(jìn)程分配獨(dú)立的資源,包括但不限于內(nèi)存空間、CPU 時(shí)間、文件描述符、網(wǎng)絡(luò)端口等,每個(gè)進(jìn)程都有自己獨(dú)立的地址空間,進(jìn)程在自己的地址空間內(nèi)可以自由地訪問(wèn)和操作數(shù)據(jù),而不會(huì)干擾其他進(jìn)程的地址空間
進(jìn)程包含了程序執(zhí)行時(shí)的運(yùn)行上下文信息,運(yùn)行上下文是指進(jìn)程在執(zhí)行過(guò)程中所涉及的各種狀態(tài)和數(shù)據(jù),主要包括程序計(jì)數(shù)器、寄存器狀態(tài)、堆棧信息、內(nèi)存管理信息等,程序計(jì)數(shù)器指示了進(jìn)程下一條要執(zhí)行的指令地址,寄存器用于臨時(shí)存儲(chǔ)數(shù)據(jù)和指令操作數(shù)等,堆棧用于保存函數(shù)調(diào)用的相關(guān)信息和局部變量等,這些運(yùn)行上下文信息完整地描述了進(jìn)程當(dāng)前的執(zhí)行狀態(tài),當(dāng)進(jìn)程被調(diào)度暫?;蚧謴?fù)執(zhí)行時(shí),操作系統(tǒng)需要保存和恢復(fù)這些上下文信息,以確保進(jìn)程能夠正確地繼續(xù)執(zhí)行
進(jìn)程是構(gòu)成操作系統(tǒng)中并發(fā)執(zhí)行環(huán)境的基本單元,操作系統(tǒng)通過(guò)管理和調(diào)度多個(gè)進(jìn)程,實(shí)現(xiàn)了多個(gè)任務(wù)的并發(fā)執(zhí)行,從而提高了系統(tǒng)資源的利用率和系統(tǒng)的整體性能,多個(gè)進(jìn)程之間可以通過(guò)各種進(jìn)程間通信機(jī)制進(jìn)行數(shù)據(jù)交換和協(xié)作,共同完成復(fù)雜的系統(tǒng)任務(wù)
下圖是我們Windows中的進(jìn)程
進(jìn)程粗略來(lái)講就是內(nèi)核PCB數(shù)據(jù)結(jié)構(gòu)對(duì)象+你自己的代碼和數(shù)據(jù)
記住上面所說(shuō)的先描述后組織,通過(guò)結(jié)構(gòu)體描述進(jìn)程的屬性,然后通過(guò)鏈表組織多個(gè)進(jìn)程
2、PCB和task_struct
進(jìn)程的所有信息被存放在一個(gè)叫做進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中,它是進(jìn)程屬性的集合,被稱為PCB
Linux操作系統(tǒng)下的PCB就是task_struct,它是一個(gè)結(jié)構(gòu)體,被裝載到RAM里
以下是task_struct的內(nèi)容分類,除了這些,還有一些其他信息
內(nèi)容 | 意義 |
---|---|
標(biāo)示符 | 每個(gè)進(jìn)程的標(biāo)識(shí)符不同 |
狀態(tài) | 任務(wù)狀態(tài) |
優(yōu)先級(jí) | 相對(duì)于其他進(jìn)程的優(yōu)先級(jí) |
程序計(jì)數(shù)器 | 程序中即將被執(zhí)行的下一條指令的地址 |
內(nèi)存指針 | 包括程序代碼和進(jìn)程相關(guān)數(shù)據(jù)的指針,還有和其他進(jìn)程共享的內(nèi)存塊的指針 |
上下文數(shù)據(jù) | 進(jìn)程執(zhí)行時(shí)處理器的寄存器中的數(shù)據(jù) |
IO狀態(tài) | 顯示的IO請(qǐng)求,分配給進(jìn)程的IO設(shè)備和被進(jìn)程使用的文件列表 |
記賬信息 | 處理器時(shí)間總和或使用的時(shí)鐘數(shù)總和或時(shí)間限制、記賬號(hào)等 |
所有運(yùn)行在系統(tǒng)里的進(jìn)程都以task_struct(雙向)鏈表的形式存在內(nèi)核里
3、查看進(jìn)程
寫(xiě)一個(gè)死循環(huán)的程序,方便我們查看進(jìn)程
ps aux | grep process | grep -v grep 查看進(jìn)程指令
ps aux 會(huì)列出系統(tǒng)中所有用戶的所有進(jìn)程的詳細(xì)信息,grep process 會(huì)在 ps aux 輸出的所有行中查找包含 process 的行,并將這些行輸出,grep 是要排除的模式,由于在執(zhí)行 grep process 時(shí),這個(gè) grep 命令本身也會(huì)作為一個(gè)進(jìn)程被 ps aux 列出,并且會(huì)匹配 process,為了避免將 grep process 這個(gè)進(jìn)程本身顯示出來(lái),我們使用 grep -v grep 來(lái)過(guò)濾掉包含 grep 的行
在程序執(zhí)行過(guò)程中會(huì)生成一個(gè)進(jìn)程,我們通過(guò)查看進(jìn)程指令,其中第二列就是進(jìn)程唯一標(biāo)識(shí)PID
進(jìn)程重啟對(duì)應(yīng)的PID會(huì)發(fā)生變化,是由于內(nèi)存重新給它分配的原因
這里解答一下為什么我們?cè)谶M(jìn)行./process的時(shí)候會(huì)啟動(dòng)可執(zhí)行文件process:在進(jìn)程中有一個(gè)目錄叫做cwd,意味著當(dāng)前的工作目錄,你可以把它想象為一個(gè)指針(其實(shí)它是一個(gè)軟鏈接),指向這個(gè)文件所在的目錄,所以一個(gè)進(jìn)程在屬性中就有一個(gè)是當(dāng)前的工作目錄
亦可以看到exe這里指向的是這里的我們正在執(zhí)行的可執(zhí)行程序process
4、通過(guò)系統(tǒng)調(diào)用fork創(chuàng)建進(jìn)程
(1)簡(jiǎn)述
上面的進(jìn)程是在執(zhí)行可執(zhí)行程序的時(shí)候程序自動(dòng)構(gòu)建的進(jìn)程,這節(jié)我們要通過(guò)系統(tǒng)調(diào)用fork創(chuàng)建進(jìn)程
寫(xiě)一個(gè)fork創(chuàng)建進(jìn)程的程序如下test.c,在我們現(xiàn)有的知識(shí)體系里,在fork函數(shù)自身不出現(xiàn)問(wèn)題的情況下給到的id值是大于等于0的值,屬于雙分支結(jié)構(gòu),即id值要不然就等于0要不然就大于0,不會(huì)出現(xiàn)即等于0又大于0的情況,本身兩種情況同時(shí)出現(xiàn)就是錯(cuò)誤的
看到結(jié)果,兩個(gè)分支的程序都會(huì)執(zhí)行,就是因?yàn)閒ork這里的原因,生成了子進(jìn)程,改變了我們對(duì)該程序固有的看法,現(xiàn)在我們來(lái)研究fork是如何做到的
(2)系統(tǒng)調(diào)用生成子進(jìn)程的過(guò)程
〇提出問(wèn)題
該過(guò)程我們可以簡(jiǎn)化為一個(gè)問(wèn)題:為什么id在等于0的同時(shí)又大于0?
id值是從fork函數(shù)來(lái)的,那么進(jìn)一步提出問(wèn)題:fork為什么能產(chǎn)生兩個(gè)返回值? id為什么能承載兩個(gè)返回值?
最終我們將目光移動(dòng)到fork函數(shù)身上
①fork函數(shù)
fork系統(tǒng)調(diào)用用于從一個(gè)現(xiàn)有的進(jìn)程創(chuàng)建一個(gè)新的進(jìn)程,新創(chuàng)建的進(jìn)程被稱為子進(jìn)程,而原來(lái)的進(jìn)程被稱為父進(jìn)程,子進(jìn)程是父進(jìn)程的一個(gè)副本,它幾乎繼承了父進(jìn)程的所有資源,包括代碼段、數(shù)據(jù)段、堆、棧等,但擁有自己獨(dú)立的進(jìn)程控制塊(PCB)和進(jìn)程 ID(PID)
在父進(jìn)程中,fork返回子進(jìn)程的 PID,因?yàn)楦高M(jìn)程可能需要對(duì)多個(gè)子進(jìn)程進(jìn)行管理和控制,所以通過(guò)返回的 PID 來(lái)標(biāo)識(shí)每個(gè)子進(jìn)程
在子進(jìn)程中,fork返回 0,這是因?yàn)樽舆M(jìn)程不需要知道父進(jìn)程的 PID 來(lái)進(jìn)行后續(xù)操作,它可以通過(guò)getppid函數(shù)來(lái)獲取父進(jìn)程的 PID
如果fork調(diào)用失敗,將返回 - 1,并設(shè)置errno變量來(lái)表示錯(cuò)誤原因
②父子進(jìn)程關(guān)系
進(jìn)程可以粗略表示為代碼+數(shù)據(jù)
當(dāng)父進(jìn)程調(diào)用fork時(shí),內(nèi)核會(huì)為子進(jìn)程分配新的 PCB,并復(fù)制父進(jìn)程的大部分資源到子進(jìn)程中,這包括進(jìn)程的代碼部分
雖然子進(jìn)程最初復(fù)制了父進(jìn)程的地址空間,但在實(shí)際運(yùn)行中,父子進(jìn)程的地址空間是相互獨(dú)立的,如果其中一個(gè)進(jìn)程修改了某些數(shù)據(jù),不會(huì)影響到另一個(gè)進(jìn)程中的相應(yīng)區(qū)域,這是通過(guò)寫(xiě)時(shí)復(fù)制技術(shù)來(lái)實(shí)現(xiàn)的,即只有當(dāng)進(jìn)程試圖修改某個(gè)數(shù)據(jù)時(shí),才會(huì)真正復(fù)制該數(shù)據(jù),以節(jié)省內(nèi)存資源,就是說(shuō)在不修改某些數(shù)據(jù)的情況下它們指向的是同一塊位置,如果子進(jìn)程或者父進(jìn)程某些數(shù)據(jù)要修改,它們會(huì)重新開(kāi)辟一塊空間存放該進(jìn)程的特有數(shù)據(jù)
fork調(diào)用完成后,父進(jìn)程和子進(jìn)程就開(kāi)始并發(fā)執(zhí)行,它們可以各自獨(dú)立地執(zhí)行不同的代碼路徑,也可以通過(guò)各種進(jìn)程間通信機(jī)制進(jìn)行通信和同步,這里就是從fork函數(shù)出現(xiàn)之后的代碼我們可以把它當(dāng)做兩份,兩份代碼同時(shí)跑,但是id不同,后面執(zhí)行的效果可能就不同
并且我們可以發(fā)現(xiàn)上面的截圖父子進(jìn)程誰(shuí)先運(yùn)行是不確定的,這個(gè)是由調(diào)度器決定的
③解答問(wèn)題
問(wèn):id為什么能承載兩個(gè)返回值?
答:id變量并不是同時(shí)承載兩個(gè)返回值,而是在不同的執(zhí)行流(父進(jìn)程和子進(jìn)程)中被賦予不同的值,fork函數(shù)通過(guò)這種方式讓父進(jìn)程和子進(jìn)程能夠區(qū)分彼此,并根據(jù)返回值執(zhí)行不同的操作
問(wèn):fork為什么能產(chǎn)生兩個(gè)返回值?
答:父子進(jìn)程并發(fā)執(zhí)行,每個(gè)執(zhí)行流從fork函數(shù)的返回處繼續(xù)執(zhí)行,并且根據(jù)自身的角色(父進(jìn)程或子進(jìn)程)返回不同的值,這樣就實(shí)現(xiàn)了一個(gè)函數(shù)調(diào)用在兩個(gè)進(jìn)程中產(chǎn)生不同返回結(jié)果的效果
今日分享就到這里了~