在操作系統(tǒng)中,設定了進程和線程的概念去描述程序并發(fā)執(zhí)行邏輯公般。本文屬于研究進程和線程的入門級文章。主要從以下五個方面介紹進程以及線程的相關概念。
- 進程和線程的定義
- 操作系統(tǒng)中對進程和線程的描述
- 進程的多層調(diào)度
- 進程/線程之間的同步機制
- 進程/線程之間的通信機制
- 如何避免進程和線程之間的死鎖
一丶進程和線程的定義
- 進程: 進程是操作系統(tǒng)中定義擁有資源和調(diào)度基本單位
- 線程:線程是操作系統(tǒng)中調(diào)度的基本單位厦酬,線程不能擁有資源,可以看成輕量級的線程瘫想。
二丶操作系統(tǒng)中對進程和線程的描述
1. 進程和線程實體描述
進程和線程均是OS中的運行實體仗阅,都是調(diào)度和分派的基本單位。
- OS定義了PCB(Proccess control block国夜,進程控制塊)描述進程實體
- OS定義TCP(Thread control block减噪,線程控制塊)描述線程實體
OS在創(chuàng)建進程/線程的時候必須創(chuàng)建對應的PCB以及TCP。PCB和TCP中存儲的內(nèi)容高低相似车吹,本文僅描述PCB的具體內(nèi)容筹裕,TCP的相關的內(nèi)容可類比。
PCB的主要內(nèi)容:
(1)進程標識符窄驹,主要用于操作系統(tǒng)以及用戶定位不同的進程朝卒,是進程的唯一標識
(2)處理機狀態(tài),在發(fā)生進程切換時保存當前處理器寄存器相關信息乐埠。處理機狀態(tài)信息也用于進程調(diào)度時恢復現(xiàn)場信息抗斤。
(3)進程調(diào)度信息,主要保存服務進程調(diào)度的相同統(tǒng)計值饮戳。比如當前進程狀態(tài)豪治,進程優(yōu)先級,已執(zhí)行CPU時間扯罐,已等待CPU時間等信息负拟,進程阻塞原因等信息內(nèi)容。
(4)進程控制信息:主要保存進程執(zhí)行相關的信息歹河,比如:(1)程序和數(shù)據(jù)的內(nèi)存地址(2) 同步和通信機制(3)進程和線程運行所需要的資源清單
2. 進程和線程的狀態(tài)描述
- 創(chuàng)建狀態(tài):進程剛創(chuàng)建的時候的狀態(tài)掩浙,此時操作系統(tǒng)剛給線程分配完PCB等空間
- 就緒狀態(tài):進程創(chuàng)建完畢后花吟,獲取了除CPU外,需要的所有資源
- 執(zhí)行狀態(tài):處于就緒狀態(tài)的進程獲取了CPU時間片后切換至執(zhí)行狀態(tài)厨姚。當進程所獲時間片消耗完畢后衅澈,將切換至就緒狀態(tài)等待下一次時間片分配。
- 阻塞狀態(tài):處于執(zhí)行狀態(tài)的進程谬墙,發(fā)生了某種使進程暫停執(zhí)行的事件今布,放棄CPU的執(zhí)行時間,進入阻塞狀態(tài)拭抬。比如競爭臨界資源部默,等待IO等事件。位于阻塞狀態(tài)的進程造虎,獲取到等待資源后傅蹂,將進入就緒狀態(tài)等待CPU分配時間片。
- 銷毀狀態(tài):進程完成執(zhí)行邏輯后算凿,進入銷毀狀態(tài)份蝴,回收內(nèi)存以及分配的資源。
三丶進程的多層調(diào)度
從硬盤上的可執(zhí)行文件搖身轉(zhuǎn)為內(nèi)存中的執(zhí)行進程涉及到如下兩層調(diào)度
(1)作業(yè)調(diào)度:作業(yè)調(diào)度是將硬盤上執(zhí)行文件調(diào)度到內(nèi)存中成為進程的過程氓轰,經(jīng)歷過該調(diào)度的進程處于就緒狀態(tài)等待分配CPU資源婚夫。當有多個作業(yè)請求調(diào)度時,有許多經(jīng)典算法可以采用
- 先來先服務算法: 按照作業(yè)請求調(diào)度的先后順序執(zhí)行調(diào)度
- 優(yōu)先級調(diào)度算法:每個作業(yè)均存在優(yōu)先級戒努,按照作業(yè)的的優(yōu)先級進行調(diào)度
- 短作業(yè)有限算法:有限調(diào)度執(zhí)行時間比較短的作業(yè)请敦。
(2)進程調(diào)度:進程調(diào)度是指在就緒隊列中排隊的就緒進程獲取CPU時間片資源的過程镐躲。進程調(diào)度算法是需要介紹的重點,從較大的方向上分储玫,其主要包括兩類:
-
基于優(yōu)先權(quán)調(diào)度的算法,該調(diào)度算法主要區(qū)分以下四種概念
- 靜態(tài)優(yōu)先權(quán)調(diào)度:靜態(tài)優(yōu)先權(quán)是指萤皂,該進程所分配的優(yōu)先權(quán)在運行的過程中是不可變化的撒穷,從始至終就是初始化的大小。
- 動態(tài)優(yōu)先權(quán)調(diào)度:進程調(diào)度的優(yōu)先權(quán)可以依據(jù)運行時的情況動態(tài)改變裆熙。比如提高排隊時間過長的進程優(yōu)先權(quán)端礼。這樣能避免饑餓進程。
- 搶占式調(diào)度:當前執(zhí)行進程的優(yōu)先權(quán)若小于排隊進程進程的優(yōu)先權(quán)入录,當前執(zhí)行進程將讓出CPU時間蛤奥,退出執(zhí)行。
- 非搶占式調(diào)度:當前進程一旦獲取了CPU執(zhí)行時間后僚稿,便不會因為優(yōu)先權(quán)的原因讓出CPU時間凡桥。除非主動結(jié)束執(zhí)行或者遇見異常情況。
基于時間片輪轉(zhuǎn)調(diào)度算法
基于時間片的調(diào)度算法將就緒進程排列成一個隊列蚀同,為隊列中每個就緒進程分配指定的時間片資源缅刽。若在規(guī)定的時間片內(nèi)進程未執(zhí)行完畢啊掏,那么該進程將再次加入隊列的尾部等待下一次時間片資源分配。上述只是基于時間片的調(diào)度算法的一般思想衰猛,在實際工業(yè)場景下過于粗糙迟蜜。下面介紹一種較為常用的多級反饋隊列調(diào)度算法具有更大的實用價值
-
多級反饋調(diào)度算法:
- 從圖中可知,該算法擁有N個用于調(diào)度的就緒隊列啡省。當進程剛進入就緒狀態(tài)時時娜睛,首先進入1級就緒隊列等待CPU分配時間片資源。若未在當前時間片資源內(nèi)執(zhí)行完畢卦睹,那么進入2級就緒隊列微姊。后續(xù)調(diào)度過程以此類推。
- 只有1級就緒隊列中沒有任何進程時分预,2級就緒隊列中的進程才能調(diào)度之CPU兢交。
- 從高級就緒隊列中調(diào)度到CPU時,會獲取更多的時間片資源笼痹。TN>T3>T2>T1.
多級反饋調(diào)度算法配喳,其優(yōu)越性一般體現(xiàn)在如下三點:
- 適用于較短的交互型任務。交互型任務一般只需要較短的執(zhí)行時間能在1級隊列中完成凳干,需要極低的響應延遲
- 在多級調(diào)度的過程中晴裹,短作業(yè)最多在1-2個時間片輪轉(zhuǎn)中可以調(diào)度完成。周轉(zhuǎn)時間任然較短
- 長作業(yè)救赐,可以輪轉(zhuǎn)到高級就緒隊列中涧团,這樣或許更多CPU執(zhí)行時間。不至于因為短作業(yè)過程经磅,長作業(yè)分配不到CPU資源而導致饑餓泌绣。
三丶進程/線程之間同步機制
進程與進程之間的同步,線程和線程之間的同步基本一致预厌。本文以線程和線程之間的同步為例子介紹同步概念阿迈。
- 線程同步的概念:線程之間并不是孤立的執(zhí)行,而是有序協(xié)作的向前推進執(zhí)行轧叽。
-
經(jīng)典的進程同步問題:
1. 消費者與生產(chǎn)者問題
消費者線程和生產(chǎn)者線程同時訪問一個總大小為N的臨界資源池苗沧。當資源池中資源數(shù)目為N時,生產(chǎn)者線程不能往其中添加數(shù)據(jù)炭晒,此時臨界資源池記為滿狀態(tài)待逞。當資源池中資源數(shù)目為0時,消費者線程不能從資源池中拿去數(shù)據(jù)网严,此時臨界資源池記為空狀態(tài)识樱。在這樣一個場景下,需要實現(xiàn)三個點:
- 消費者線程和生產(chǎn)者線程臨界資源池的訪問是互斥的。
- 臨界資源池在滿狀態(tài)時牺荠,生產(chǎn)者線程放入數(shù)據(jù)操作必須阻塞翁巍,等待資源池非滿狀態(tài)時才能繼續(xù)放入
- 臨界資源池空狀態(tài)時,消費者線程取數(shù)據(jù)的操作必須阻塞休雌,等待資源池非空狀態(tài)時才能繼續(xù)取出灶壶。
解決方法:互斥鎖以及條件變量
2. 哲學家就餐問題
從上圖可知,五個哲學家們圍坐在一個圓桌上杈曲,每個哲學家左右兩側(cè)都放了一只筷子驰凛。當哲學家們想要就就餐時,會試圖拿起離自己最近的筷子担扑。一只一只這樣拿筷子恰响。當哲學家拿齊一雙筷子后,就開始就餐涌献。就餐完畢后將所有筷子放回原處胚宦,開始思考哲學。
那么為什么要構(gòu)造出這樣一個關于哲學家就餐的場景呢燕垃?
主要是構(gòu)建出一個因為線程同步不當而造成死鎖的場景枢劝,倘若哲學家門同時拿起來自己左側(cè)的筷子后,當哲學再次試圖去拿右側(cè)筷子時卜壕,所有哲學家都無法獲取就餐機會您旁,陷入僵局。這也是進程同步中的死鎖問題轴捎。上述哲學家問題中死鎖情況存在下述解決方案
(1) 至多只能允許最多四個哲學家同時去拿同一側(cè)的筷子
(2) 哲學家同時拿起兩只筷子鹤盒,而不一只只拿。
可以看出上述解決方法侦副,都是通過設置限制條件侦锯,避免死鎖情況發(fā)生。
3. 讀者-寫者問題
對于一個文件跃洛,存在多個線程同時讀取以及多個線程同時寫入率触。在這種條件下要求對文件的訪問不能混亂终议。那么要求讀線程和寫線程必須滿足如下要求:
- 讀線程和寫線程之間對文件的訪問是互斥的
- 寫線程之間對文件的訪問是互斥的
- 讀線程之間對文件的訪問不需要互斥
解決方法: 讀寫鎖
四丶如何避免進程/線程之間的死鎖
本節(jié)從線程的角度來介紹死鎖汇竭。線程死鎖是線程同步不當導致的問題。本節(jié)將從線程死鎖原因穴张,線程死鎖的必要條件细燎,以及規(guī)避線程死鎖的三個方面來分析。
1. 線程死鎖產(chǎn)生的原因
以哲學家就餐問題皂甘,來研究線程死鎖原因
- 競爭共享資源:哲學家所需要的筷子就是共享資源玻驻。倘若哲學家們存在一雙私有的筷子那么變不存在死鎖問題。
- 進程間推進順序不合理: 競爭共享資源并不一會導致死鎖。在哲學家就餐問題中璧瞬,如果能夠避免同時拿起同一側(cè)筷子這種運行順序户辫。那么不會發(fā)生死鎖。盡管進程之間存在共享資源競爭嗤锉,但是只要推進順序合理便能避免死鎖渔欢。
2. 線程死鎖產(chǎn)生的必要條件
死鎖發(fā)生具有四個必備條件,當能夠同時滿足這四個條件時瘟忱,便有可能發(fā)生死鎖奥额。
- 互斥條件,線程對資源的獲取具有排他性访诱,在獲取資源的同時獨占資源垫挨,不允許其他線程訪問共享資源
- 請求和保持條件,線程在獲取某個資源之后触菜,若再次申請或許新的資源但被阻塞時九榔,并不釋放已占有的資源
- 不剝奪條件,線程獲取資源之后涡相,不會因為其他線程競爭而放棄資源帚屉。只能等到使用完畢或者主動釋放
- 環(huán)路條件,當線程之間發(fā)生死鎖的時候,必然存在一個線程->資源之間的環(huán)形鏈路漾峡。比如線程P1等到線程P2占用的某個資源攻旦,線程P2等待線程P1占用的謀和資源
3. 避免死鎖的方法
- 預防死鎖:通過破壞死鎖產(chǎn)生的必要條件,在預防死鎖的發(fā)生
- 避免死鎖:在對線程分配資源的時候生逸,計算該次資源分配之后線程是否處于安全狀態(tài)牢屋。處于安全狀態(tài)則分配資源,否則并不分配資源槽袄。避免死鎖具有代表性的算法便是銀行家算法烙无。這是一種非常經(jīng)典的預防死鎖的方法
- 檢測和接觸死鎖:該種方法在進程競爭資源的時候,并不任何預防或者避免死鎖的方法遍尺。它僅僅提供對死鎖的發(fā)現(xiàn)機制截酷,在產(chǎn)生死鎖之后,通過殺死死鎖線程達到接觸死鎖的目的乾戏。
五丶進程/線程之間通信機制
進程/線程之間的同步其實是一種通信機制迂苛,但是同步機制只是一種小規(guī)模的數(shù)據(jù)通信。此處介紹的通信機制是應對較大規(guī)模的數(shù)據(jù)傳輸鼓择。此處以進程之間的通信機制為例介紹
- 共享存儲系統(tǒng)
共享存儲系統(tǒng)比較容易理解三幻,就是多個進程擁有共同存儲空間,通過修改/讀取同一塊區(qū)域達到通信目的呐能。 - 消息傳遞系統(tǒng)
消息傳遞系統(tǒng)是指進程之間通過格式化數(shù)據(jù)報文交換信息念搬,最容易理解的便是計算機網(wǎng)絡數(shù)據(jù)報文交換。位于不同計算機上應用的通信也是進程通信的一種場景 - 管道通信
所謂"管道"是指用于連接一個讀進程和一個寫進程以實現(xiàn)他們之間的通信的一個文件。向管道(共享文件)輸入的發(fā)送進程朗徊,以字符流的形式輸入大量數(shù)據(jù)到管道中首妖,從管道接收輸出的接收進程,將讀取大量數(shù)據(jù)爷恳。