程概念)
1、馮諾依曼體系結(jié)構(gòu)我們常用的計(jì)算機(jī)服務(wù)器等大部分都遵守馮諾依曼體系。關(guān)于馮諾依曼必須強(qiáng)調(diào)幾點(diǎn)這里的存儲(chǔ)器指的是內(nèi)存不考慮緩存情況這里的CPU能且只能對(duì)內(nèi)存進(jìn)行讀寫不能訪問外設(shè)(輸入或輸出設(shè)備)(數(shù)據(jù)層面)外設(shè)(輸入或輸出設(shè)備)要輸入或者輸出數(shù)據(jù)也只能寫入內(nèi)存或者從內(nèi)存中讀取。?句話所有設(shè)備都只能直接和內(nèi)存打交道。2、操作系統(tǒng)任何計(jì)算機(jī)系統(tǒng)都包含?個(gè)基本的程序集合稱為操作系統(tǒng)(OS)?;\統(tǒng)的理解操作系統(tǒng)包括內(nèi)核進(jìn)程管理內(nèi)存管理文件管理驅(qū)動(dòng)管理其他程序例如函數(shù)庫shell程序等等設(shè)計(jì)OS的目的對(duì)下與硬件交互管理所有的軟硬件資源對(duì)上為用戶程序應(yīng)用程序提供?個(gè)良好的執(zhí)行環(huán)境3、進(jìn)程進(jìn)程 內(nèi)核數(shù)據(jù)結(jié)構(gòu)(task_struct) 自己的程序代碼和數(shù)據(jù)3.1 描述進(jìn)程-PCB基本概念進(jìn)程信息被放在?個(gè)叫做進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中可以理解為進(jìn)程屬性的集合。課本上稱之為PCBprocess control block Linux 操作系統(tǒng)下的 PCB 是: task_structtask_struct是PCB的?種在 Linux 中描述進(jìn)程的結(jié)構(gòu)體叫做 task_struct 。task_struct 是 Linux 內(nèi)核的?種數(shù)據(jù)結(jié)構(gòu)類型它會(huì)被裝載到RAM(內(nèi)存)里并且包含著進(jìn)程的信息。3.2 task_ struct內(nèi)容分類標(biāo)示符: 描述本進(jìn)程的唯?標(biāo)示符用來區(qū)別其他進(jìn)程。狀態(tài): 任務(wù)狀態(tài)退出代碼退出信號(hào)等。優(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ù)I ∕ O狀態(tài)信息: 包括顯示的I/O請(qǐng)求,分配給進(jìn)程的I∕O設(shè)備和被進(jìn)程使用的文件列表。記賬信息: 可能包括處理器時(shí)間總和使用的時(shí)鐘數(shù)總和時(shí)間限制記賬號(hào)等。其他信息所有運(yùn)行在系統(tǒng)里的進(jìn)程都以 task_struct 雙鏈表的形式存在內(nèi)核里。3.3 查看進(jìn)程進(jìn)程的信息可以通過 /proc 系統(tǒng)文件夾查看大多數(shù)進(jìn)程信息同樣可以使用top和ps這些用戶級(jí)?具來獲取3.4 通過系統(tǒng)調(diào)用創(chuàng)建進(jìn)程-fork初識(shí)fork有兩個(gè)返回值 父子進(jìn)程代碼共享數(shù)據(jù)各自開辟空間私有一份采用寫時(shí)拷貝1. fork 為什么會(huì)有兩個(gè)返回值不是一個(gè)函數(shù)返回兩次而是調(diào)用 fork 之后操作系統(tǒng)創(chuàng)建了一個(gè)新進(jìn)程變成兩個(gè)進(jìn)程各自執(zhí)行 fork 之后的代碼各自拿到一份返回值。調(diào)用fork()之前只有父進(jìn)程這 1 個(gè)進(jìn)程在運(yùn)行。調(diào)用fork()的一瞬間OS 復(fù)制父進(jìn)程創(chuàng)建出子進(jìn)程子進(jìn)程幾乎完整拷貝父進(jìn)程的地址空間、代碼、數(shù)據(jù)。fork系統(tǒng)調(diào)用在父進(jìn)程里返回一次同時(shí)在新建出來的子進(jìn)程里再返回一次。所以代碼上看起來同一個(gè)fork調(diào)用出現(xiàn)兩個(gè)返回值。本質(zhì)是兩個(gè)獨(dú)立進(jìn)程各自拿到返回值。2. 兩個(gè)返回值分別給誰父進(jìn)程fork返回 0 的正數(shù)這個(gè)數(shù)字就是子進(jìn)程的 PID進(jìn)程號(hào)。子進(jìn)程fork返回0。出錯(cuò)情況fork 失敗進(jìn)程數(shù)量上限等返回-1此時(shí)不會(huì)創(chuàng)建子進(jìn)程。3.同一個(gè)變量 ret為什么 if 和 else if 可以同時(shí)成立很多初學(xué)者會(huì)疑惑ret 一個(gè)變量怎么if(ret0)和else if(ret0)都執(zhí)行真相不是同一個(gè)變量fork創(chuàng)建子進(jìn)程時(shí)會(huì)拷貝父進(jìn)程的內(nèi)存子進(jìn)程擁有屬于自己獨(dú)立的地址空間。父進(jìn)程內(nèi)存里的ret存的是子進(jìn)程 PID正數(shù)子進(jìn)程內(nèi)存里的ret存的是 0兩個(gè)進(jìn)程兩份獨(dú)立的 ret 變量各自走自己的分支。父進(jìn)程走else if(ret0)子進(jìn)程走if(ret0)兩個(gè)分支分別在兩個(gè)進(jìn)程里面運(yùn)行互不干擾。并不是單進(jìn)程里面一個(gè)變量同時(shí)等于 0 又大于 0。3.5 進(jìn)程狀態(tài)?個(gè)進(jìn)程可以有幾個(gè)狀態(tài)在Linux內(nèi)核里進(jìn)程有時(shí)候也叫做任務(wù)R運(yùn)行狀態(tài)running: 并不意味著進(jìn)程?定在運(yùn)行中它表明進(jìn)程要么是在運(yùn)行中要么在運(yùn)行隊(duì)列里。S睡眠狀態(tài)sleeping): 意味著進(jìn)程在等待事件完成這里的睡眠有時(shí)候也叫做可中斷睡眠interruptible sleep。D磁盤休眠狀態(tài)Disk sleep有時(shí)候也叫不可中斷睡眠狀態(tài)uninterruptible sleep在這個(gè)狀態(tài)的進(jìn)程通常會(huì)等待IO的結(jié)束。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)。進(jìn)程狀態(tài)查看ps aux / ps axj 命令a顯示?個(gè)終端所有的進(jìn)程包括其他用戶的進(jìn)程。x顯示沒有控制終端的進(jìn)程例如后臺(tái)運(yùn)行的守護(hù)進(jìn)程。j顯示進(jìn)程歸屬的進(jìn)程組ID、會(huì)話ID、父進(jìn)程ID以及與作業(yè)控制相關(guān)的信息u以用戶為中心的格式顯示進(jìn)程信息提供進(jìn)程的詳細(xì)信息如有用戶、CPU和內(nèi)存使用情況等3.51 僵尸進(jìn)程僵死狀態(tài)Zombies是一個(gè)比較特殊的狀態(tài)。當(dāng)進(jìn)程退出并且父進(jìn)程沒有讀取到子進(jìn)程退出的返回代碼時(shí)就會(huì)產(chǎn)生僵死進(jìn)程僵死進(jìn)程會(huì)以終止?fàn)顟B(tài)保持在進(jìn)程表中并且會(huì)?直在等待父進(jìn)程讀取退出狀態(tài)代碼因?yàn)樾枰嬖V父進(jìn)程任務(wù)進(jìn)行得怎么樣。所以只要子進(jìn)程退出父進(jìn)程還在運(yùn)行但父進(jìn)程沒有讀取子進(jìn)程狀態(tài)子進(jìn)程進(jìn)入Z狀態(tài)僵尸進(jìn)程的危害僵尸進(jìn)程已釋放用戶態(tài)內(nèi)存但內(nèi)核中 task_struct 等 PCB 資源未釋放會(huì)造成內(nèi)核內(nèi)存資源泄漏。它持續(xù)占用 PID 與內(nèi)核進(jìn)程表項(xiàng)大量堆積會(huì)耗盡 PID導(dǎo)致系統(tǒng)無法創(chuàng)建新進(jìn)程。大量僵尸進(jìn)程還會(huì)干擾進(jìn)程排查掩蓋系統(tǒng)其他異常問題。3.52 孤兒進(jìn)程問題父進(jìn)程如果提前退出那么子進(jìn)程后退出進(jìn)入Z之后那該如何處理呢父進(jìn)程先退出子進(jìn)程就稱之為“孤兒進(jìn)程”孤兒進(jìn)程被1號(hào)init / systemd進(jìn)程領(lǐng)養(yǎng)當(dāng)然要有init / systemd進(jìn)程回收模擬孤兒進(jìn)程3.6 進(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上這樣?來把不重要的進(jìn)程安排到某個(gè)CPU可以改善系統(tǒng)整體性能。3.61 查看系統(tǒng)進(jìn)程在linux或者unix系統(tǒng)中用ps ?l命令則會(huì)類似輸出以下幾個(gè)內(nèi)容我們很容易注意到其中的幾個(gè)重要信息有下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值3.62 PRI and NIPRI也還是比較好理解的即進(jìn)程的優(yōu)先級(jí)或者通俗點(diǎn)說就是程序被CPU執(zhí)行的先后順序此值越小進(jìn)程的優(yōu)先級(jí)別越高那NI呢?就是我們所要說的nice值了其表示進(jìn)程可被執(zhí)行的優(yōu)先級(jí)的修正數(shù)值PRI值越小越快被執(zhí)行那么加入nice值后將會(huì)使得PRI變?yōu)镻RI(new)PRI(old)nice這樣當(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í)別。3.63 PRI vs NI需要強(qiáng)調(diào)?點(diǎn)的是進(jìn)程的nice值不是進(jìn)程的優(yōu)先級(jí)他們不是?個(gè)概念但是進(jìn)程nice值會(huì)影響到進(jìn)程的優(yōu)先級(jí)變化??梢岳斫鈔ice值是進(jìn)程優(yōu)先級(jí)的修正數(shù)據(jù)3.64 查看進(jìn)程優(yōu)先級(jí)的命令?top命令更改已存在進(jìn)程的nicetop進(jìn)入top后按“r”?輸入進(jìn)程PID?輸入nice值3.7 進(jìn)程切換CPU上下文切換其實(shí)際含義是任務(wù)切換, 或者CPU寄存器切換。當(dāng)多任務(wù)內(nèi)核決定運(yùn)行另外的任務(wù)時(shí), 它保存正在運(yùn)行任務(wù)的當(dāng)前狀態(tài), 也就是CPU寄存器中的全部?jī)?nèi)容。這些內(nèi)容被保存在任務(wù)自己的堆棧中, 入棧工作作完成后就把下?個(gè)將要運(yùn)行的任務(wù)的當(dāng)前狀況從該任務(wù)的棧中重新裝入CPU寄存器,并開始下?個(gè)任務(wù)的運(yùn)行, 這?過程就是context switch。每個(gè)進(jìn)程都會(huì)分配對(duì)應(yīng)的時(shí)間片如果沒在時(shí)間片指定的時(shí)間內(nèi)完成任務(wù)該進(jìn)程會(huì)被暫時(shí)切下來需要進(jìn)程自己保存自己得上下文數(shù)據(jù)目的是下次回來能夠恢復(fù)按照之前得邏輯向后運(yùn)行。3.8 Linux內(nèi)核進(jìn)程O(1)調(diào)度隊(duì)列時(shí)間片還沒有結(jié)束的所有進(jìn)程都按照優(yōu)先級(jí)放在該隊(duì)列nr_active: 總共有多少個(gè)運(yùn)行狀態(tài)的進(jìn)程queue[140]: ?個(gè)元素就是?個(gè)進(jìn)程隊(duì)列相同優(yōu)先級(jí)的進(jìn)程按照FIFO規(guī)則進(jìn)行排隊(duì)調(diào)度,所以數(shù)組下標(biāo)就是優(yōu)先級(jí)從該結(jié)構(gòu)中選擇?個(gè)最合適的進(jìn)程過程是怎么的呢從0下表開始遍歷queue[140]找到第?個(gè)非空隊(duì)列該隊(duì)列必定為優(yōu)先級(jí)最高的隊(duì)列拿到選中隊(duì)列的第?個(gè)進(jìn)程開始運(yùn)行調(diào)度完成遍歷queue[140]時(shí)間復(fù)雜度是常數(shù)bitmap[5]:?共140個(gè)優(yōu)先級(jí)?共140個(gè)進(jìn)程隊(duì)列為了提高查找非空隊(duì)列的效率就可以用5*32個(gè)比特位表示隊(duì)列是否為空3.81 過期隊(duì)列過期隊(duì)列和活動(dòng)隊(duì)列結(jié)構(gòu)?模?樣過期隊(duì)列上放置的進(jìn)程都是時(shí)間片耗盡的進(jìn)程當(dāng)活動(dòng)隊(duì)列上的進(jìn)程都被處理完畢之后對(duì)過期隊(duì)列的進(jìn)程進(jìn)行時(shí)間片重新計(jì)算3.82 active指針和expired指針active指針永遠(yuǎn)指向活動(dòng)隊(duì)列expired指針永遠(yuǎn)指向過期隊(duì)列可是活動(dòng)隊(duì)列上的進(jìn)程會(huì)越來越少過期隊(duì)列上的進(jìn)程會(huì)越來越多因?yàn)檫M(jìn)程時(shí)間片到期時(shí)?直都存在的。新加進(jìn)來的進(jìn)程也會(huì)放在過期隊(duì)列里面相當(dāng)于進(jìn)程狀態(tài)中的就緒狀態(tài)只要能夠交換active指針和expired指針的內(nèi)容就相當(dāng)于有具有了?批新的活動(dòng)進(jìn)程4、調(diào)度算法為o(1)原因從 active 選最高優(yōu)先級(jí)進(jìn)程運(yùn)行進(jìn)程時(shí)間片用完把它挪到 expired 隊(duì)列active 全部空了的時(shí)候直接交換 active 和 expired 指針不需要移動(dòng)任何進(jìn)程只是交換兩個(gè)指針變量常數(shù)操作。