前言
當(dāng)我想要進(jìn)一步了解PHP,Node.Js這些語言中的線程進(jìn)程,異步等這些概念時(shí)候嗦篱,總有些霧里看花的感覺泣洞,那么干脆就先了解下操作系統(tǒng)相關(guān)知識,再去學(xué)這些東西默色。
導(dǎo)論
計(jì)算機(jī)系統(tǒng)組織和體系
操作系統(tǒng)是管理計(jì)算機(jī)硬件的程序球凰,它還為應(yīng)用程序提供基礎(chǔ)狮腿,并且充當(dāng)計(jì)算機(jī)硬件和計(jì)算機(jī)用戶的中介。
事件的發(fā)生通常通過硬件或軟件中斷(interrupt)來表示呕诉。硬件可隨時(shí)通過系統(tǒng)總線向CPU 發(fā)出信號缘厢,以觸發(fā)中斷。軟件通過執(zhí)行特別操作如系統(tǒng)調(diào)用(system call) (也稱為監(jiān)視器調(diào)用(monitor call) )也能觸發(fā)中斷甩挫。
中斷是計(jì)算機(jī)結(jié)構(gòu)的重要部分贴硫。當(dāng)CPU 中斷時(shí),它暫停正在做的事并立即轉(zhuǎn)到固定的位置繼續(xù)執(zhí)行伊者。該固定位置通常是斷服務(wù)程序開始位置的地址英遭。中斷服務(wù)程序開始執(zhí)行,在執(zhí)行完后亦渗, CPU 重新執(zhí)行被中斷的計(jì)算挖诸。
操作系統(tǒng)結(jié)構(gòu)
操作系統(tǒng)最重要的一點(diǎn)是要有多道程序處理能力。單個(gè)用戶通常不能總是使得CPU 和I/O 設(shè)備都忙法精。多道程序設(shè)計(jì)通過組織作業(yè)(編碼或數(shù)據(jù))使CPU 總有一個(gè)作業(yè)可執(zhí)行多律,從而提高了CPU 的利用率。
這種思想如下:操作系統(tǒng)同時(shí)將多個(gè)任務(wù)保存在內(nèi)存中(見圖1.7)搂蜓。該作業(yè)集可以是作業(yè)池中作業(yè)集的子集(作業(yè)池中包括所有進(jìn)入系統(tǒng)的作業(yè)) 狼荞,這是因?yàn)榭赏瑫r(shí)保存在內(nèi)存中的作業(yè)數(shù)要比可在作業(yè)池中的作業(yè)數(shù)少。操作系統(tǒng)選擇一個(gè)位于內(nèi)存中的作業(yè)并開始執(zhí)行帮碰。最終相味,該作業(yè)可能必須等待另一個(gè)任務(wù)如I/O 操作的完成。對于非多道程序系統(tǒng)殉挽, CPU就會空閑:對于多道程序系統(tǒng)攻走, CPU 會簡單地切換到另一個(gè)作業(yè)并執(zhí)行。當(dāng)該作業(yè)需要等待時(shí)此再, CPU 會切換到另一個(gè)作業(yè)昔搂。最后,第一個(gè)作業(yè)完成等待且重新獲得CPU输拇。只要有一個(gè)任務(wù)可以執(zhí)行摘符, CPU 就決不會空閑。
多道程序系統(tǒng)提供了一個(gè)可以充分使用各種系統(tǒng)資源(如CPU 策吠、內(nèi)存逛裤、外設(shè))的環(huán)境,但是它們沒有提供與計(jì)算機(jī)系統(tǒng)直接交互的能力猴抹。分時(shí)系統(tǒng)(或多任務(wù))是多道程序設(shè)計(jì)的延伸带族。在分時(shí)系統(tǒng)中,雖然CPU 還是通過在作業(yè)之間的切換來執(zhí)行多個(gè)作業(yè)蟀给,但是由于切換頻率很高蝙砌,用戶可以在程序運(yùn)行期間與之進(jìn)行交互阳堕。
操作系統(tǒng)操作
雙重模式操作
系統(tǒng)引導(dǎo)時(shí),硬件開始處于內(nèi)核模式择克。接著恬总,裝入操作系統(tǒng),開始在用戶模式下執(zhí)行用戶進(jìn)程肚邢。一旦出現(xiàn)陷阱或中斷壹堰,硬件會從用戶模式切換到內(nèi)核模式(即將模式位設(shè)為0) 。因此骡湖,只要操作系統(tǒng)獲得了對計(jì)算機(jī)的控制贱纠,它就處于內(nèi)核模式。系統(tǒng)在將控制交還給用戶程序時(shí)會切換到用戶模式(將模式位設(shè)為1)响蕴。
雙重模式操作提供了保護(hù)操作系統(tǒng)和用戶程序不受錯(cuò)誤用戶程序影響的手段谆焊。其實(shí)現(xiàn)方法為:將能引起損害的機(jī)器指令作為特權(quán)指令(privileged instruction) 。如果在用戶模式下試圖執(zhí)行特權(quán)指令换途,那么硬件并不執(zhí)行該指令,而是認(rèn)為該指令非法刽射,并將其以陷阱的形式通知操作系統(tǒng)懈息。
定時(shí)器
必須確保操作系統(tǒng)能維持對CPU 的控制俗慈,也必須防止用戶程序陷入死循環(huán)或不調(diào)用系統(tǒng)服務(wù),井且不將控制權(quán)返回到操作系統(tǒng)瘦穆。
操作系統(tǒng)在將控制權(quán)交給用戶之前,應(yīng)確保設(shè)置好定時(shí)器以便產(chǎn)生中斷悲伶。如果定時(shí)器產(chǎn)生中斷淮椰,那么控制權(quán)會自動(dòng)交給操作系統(tǒng),而操作泵統(tǒng)可以將中斷作為致命錯(cuò)誤來處理腋粥,也可以給予用戶程序更多的時(shí)間。
進(jìn)程管理
程序在未被CPU 執(zhí)行之前不會做任何事罗珍。處于執(zhí)行中的程序被稱為進(jìn)程。
進(jìn)程需要一定的資源(包括CPU 時(shí)間扣唱、內(nèi)存度液、文件、I/O 設(shè)備)以完成其任務(wù)画舌。這些資源可以在進(jìn)程創(chuàng)建時(shí)分配給進(jìn)程堕担,也可以在執(zhí)行進(jìn)程時(shí)分配給進(jìn)程。除了在創(chuàng)建時(shí)得到各種物理和邏輯資源外曲聂,進(jìn)程還可以接受傳輸過來的各種初始化數(shù)據(jù)(輸入)霹购。例如,考慮這樣一個(gè)進(jìn)程朋腋,它的功能是在終端或者屏幕上顯示文件狀態(tài)齐疙。該進(jìn)程會得到一個(gè)文件名作為輸入膜楷,并且執(zhí)行適當(dāng)?shù)闹噶詈拖到y(tǒng)調(diào)用以得到和顯示終端所需的信息。當(dāng)進(jìn)程中止時(shí)贞奋,操作系統(tǒng)將收回所有可再用的資源赌厅。
需要強(qiáng)調(diào)的是,程序本身并不是進(jìn)程轿塔,程序是被動(dòng)的實(shí)體特愿,單線程進(jìn)程具有一個(gè)程序計(jì)數(shù)器來明確下一個(gè)執(zhí)行的指令。
進(jìn)程是系統(tǒng)工作的單元勾缭。系統(tǒng)由多個(gè)進(jìn)程組成揍障,其中一些是操作系統(tǒng)進(jìn)程(執(zhí)行系統(tǒng)代碼),其余的是用戶進(jìn)程(執(zhí)行用戶代碼)俩由。所有這些進(jìn)程可以潛在地并發(fā)執(zhí)行毒嫡,如通過在單CPU 上采用CPU 復(fù)用來實(shí)現(xiàn)。
操作系統(tǒng)結(jié)構(gòu)
操作系統(tǒng)提供若干服務(wù)幻梯。最底層兜畸,系統(tǒng)調(diào)用允許運(yùn)行程序直接向操作系統(tǒng)發(fā)出請求。在高層碘梢,命令解釋程序或 Shell 提供了一個(gè)機(jī)制以便用戶不必編寫程序就能發(fā)出請求咬摇。
請求類型隨請求級別而變化。系統(tǒng)調(diào)用級別提供基本功能痘系,如進(jìn)程控制菲嘴、文件和設(shè)備管理饿自。由命令解釋程序或系統(tǒng)程序來完成的高級別請求需要轉(zhuǎn)換成一些列的系統(tǒng)請求汰翠。系統(tǒng)服務(wù)可分成許多類型:程序控制、狀態(tài)請求和I/O請求昭雌。
在定義了系統(tǒng)服務(wù)之后复唤,就可以開發(fā)操作系統(tǒng)的結(jié)構(gòu)。需要用各種表記錄一些信息烛卧,這些信息定義了計(jì)算機(jī)的系統(tǒng)狀態(tài)和系統(tǒng)的作業(yè)狀態(tài)佛纫。
由于操作系統(tǒng)很大,所以模塊化很重要总放。按一系列或采用微內(nèi)核來設(shè)計(jì)系統(tǒng)是比較好的技術(shù)呈宇。虛擬機(jī)概念采用了分層方法,并將操作系統(tǒng)內(nèi)核和硬件都作為硬件來考慮局雄。
進(jìn)程
進(jìn)程是執(zhí)行中的程序甥啄。隨著進(jìn)程的執(zhí)行,它改變狀態(tài)炬搭。進(jìn)程狀態(tài)由進(jìn)程當(dāng)前活動(dòng)所定義蜈漓。每個(gè)進(jìn)程可處于:新的穆桂、就緒、運(yùn)行融虽、等待或終止?fàn)顟B(tài)享完。每個(gè)進(jìn)程在操作系統(tǒng)內(nèi)通過進(jìn)程控制塊(PCB)來表示。
當(dāng)前不執(zhí)行的進(jìn)程會放在某個(gè)等待隊(duì)列有额。操作系統(tǒng)有兩種主要隊(duì)列:I/O 請求隊(duì)列和就緒隊(duì)列般又。就緒隊(duì)列包括所有準(zhǔn)備執(zhí)行并等待 CPU 的進(jìn)程。每個(gè)進(jìn)程都有 PCB谆吴, PCB鏈接起來就形成了就緒隊(duì)列倒源。長期調(diào)度通過選擇進(jìn)程來爭用 CPU。通常句狼,長期調(diào)度會受資源分配考慮笋熬,尤其是內(nèi)存管理的影響。短期調(diào)度從就緒隊(duì)列中選擇進(jìn)程腻菇。
操作系統(tǒng)必須為父進(jìn)程創(chuàng)建子進(jìn)程提供一種機(jī)制胳螟。父進(jìn)程在繼續(xù)之前可以等待它的子進(jìn)程終止,也可以并發(fā)執(zhí)行父進(jìn)程和子進(jìn)程筹吐。并發(fā)執(zhí)行有許多優(yōu)點(diǎn)糖耸,例如信息共享、提供運(yùn)算速度丘薛、模塊化和便利性等嘉竟。
操作系統(tǒng)的執(zhí)行進(jìn)程可以是獨(dú)立進(jìn)程或協(xié)作進(jìn)程。協(xié)作進(jìn)程需要進(jìn)程間有互相通信的機(jī)制洋侨。主要有兩種形式的通信:共享內(nèi)存和消息系統(tǒng)舍扰。共享內(nèi)存的方法要求通信進(jìn)程共享一些變量。進(jìn)程通過使用這些共享變量來交換信息希坚。對于共享內(nèi)存系統(tǒng)边苹,主要應(yīng)用程序員提供通信,操作系統(tǒng)只需要提供共享內(nèi)存裁僧。消息系統(tǒng)方法允許進(jìn)程交換信息个束。提供通信的主要責(zé)任在于操作系統(tǒng)本身。這兩種方法并不互相排斥聊疲,能在同一操作系統(tǒng)內(nèi)同時(shí)實(shí)現(xiàn)。
客戶機(jī)-服務(wù)器系統(tǒng)中可能使用:(1)Socket获洲, (2)遠(yuǎn)程過程調(diào)用(RPC) (3)Java遠(yuǎn)程方法調(diào)用(RMI)阱表。 Socket 定義為通信的端點(diǎn)。一對應(yīng)用程序間的連接由一對 Socket 組成,每端各有一個(gè)通信頻道捶枢。 RPC 是另一種形式的分布通信握截。 當(dāng)一個(gè)進(jìn)程調(diào)用遠(yuǎn)程應(yīng)用的方法時(shí),就是 RPC烂叔。
線程
線程是進(jìn)程內(nèi)的控制流谨胞。多線程進(jìn)程在同一地址空間內(nèi)包括多個(gè)不同的控制流。多線程的優(yōu)點(diǎn)是對用戶響應(yīng)的改進(jìn)蒜鸡、進(jìn)程內(nèi)的資源共享胯努、經(jīng)濟(jì)和利用多處理器體系結(jié)構(gòu)的能力。
用戶線程對程序員來說是可見的逢防,而對內(nèi)核來說確實(shí)未知的叶沛。操作系統(tǒng)支持和管理內(nèi)核線程。通常忘朝,用戶線程跟內(nèi)核線程比灰署,創(chuàng)建和管理要更快,因?yàn)樗恍枰獌?nèi)核干預(yù)局嘁。有三種不同模型將用戶和內(nèi)核線程關(guān)聯(lián)起來:多對一模型將許多用戶線程映射到一個(gè)內(nèi)核線程:一對一模型將每個(gè)用戶線程映射到一個(gè)相應(yīng)的內(nèi)核線程溉箕;多隊(duì)多模型將多個(gè)用戶線程在同樣數(shù)量的內(nèi)核線程之間切換。
線程庫為應(yīng)用程序提供了創(chuàng)建和管理線程的API悦昵,通常由三種主要的線程庫:POSIX肴茄、Pthread API、 Windows系統(tǒng)的 Win32 線程以及 Java線程但指。
多線程程序?yàn)槌绦騿T帶來了許多挑戰(zhàn)寡痰,包括系統(tǒng)調(diào)用 fork() 和 exec() 的語義。其他事項(xiàng)包括線程取消棋凳、信號和特定線程數(shù)據(jù)拦坠。
CPU調(diào)度
CPU調(diào)度的任務(wù)就是從就緒隊(duì)列中選擇一個(gè)等待進(jìn)程,并為其分配CPU贫橙。CPU由調(diào)度程序分配給選中的進(jìn)程贪婉。
先到服務(wù)調(diào)度是最簡單的調(diào)度算法反粥,但是它會讓短進(jìn)程等到非常長的進(jìn)程卢肃。最短作業(yè)優(yōu)先調(diào)度是最佳的,它提供了最短的平均等待時(shí)間才顿。實(shí)現(xiàn) SJF 調(diào)度比較困難莫湘,因?yàn)轭A(yù)測下一個(gè) CPU 區(qū)間的長度有難度。 SJF 算法是通用優(yōu)先級調(diào)用算法的特例郑气。優(yōu)先級和 SJF 調(diào)度會產(chǎn)生饑餓幅垮。老化技術(shù)可組織饑餓。
輪轉(zhuǎn)法調(diào)度對于分時(shí)系統(tǒng)更為合適尾组。 RR 調(diào)度讓就緒隊(duì)列的第一個(gè)進(jìn)程使用 CPU 的q個(gè)時(shí)間單元忙芒,這里 q 是時(shí)間片示弓。 在 q 時(shí)間單元后,如果該進(jìn)程還沒釋放 CPU呵萨,那么被搶占并放到就緒隊(duì)列的尾部奏属。 該算法主要問題是選擇時(shí)間片。如果時(shí)間片太大潮峦,那么 RR 調(diào)度就成了 FCFS 調(diào)度囱皿; 如果時(shí)間片太小,那么因?yàn)樯舷挛那袚Q而引起的調(diào)度開銷就過大忱嘹。
FCFS算法是非搶占的嘱腥,而 RR 算法是搶占的。 SIF 和優(yōu)先級算法可以是搶占的拘悦,也可以是非搶占的齿兔。
多級隊(duì)列調(diào)度算法允許多個(gè)不同算法用于各種類型的進(jìn)程。最為常用的包括使用 RR 調(diào)度的前臺交互隊(duì)列础米,以及使用 FCFS 調(diào)度的后臺批處理隊(duì)列愧驱。多級反饋隊(duì)列調(diào)度算法允許進(jìn)程在隊(duì)列之間遷移。
總結(jié)
大致看到進(jìn)程椭盏,線程组砚,CPU調(diào)度這些之后,對這些的概念更為清晰了一些掏颊,在此基礎(chǔ)上再去理解 Python中的多進(jìn)
程糟红, 單進(jìn)程的 Node.js, PHP-FPM 感覺又清晰了一些。
--EOF--