操作系統(tǒng)中進程管理的基本原理_第1頁
操作系統(tǒng)中進程管理的基本原理_第2頁
操作系統(tǒng)中進程管理的基本原理_第3頁
操作系統(tǒng)中進程管理的基本原理_第4頁
操作系統(tǒng)中進程管理的基本原理_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

操作系統(tǒng)中進程管理的基本原理作者:石瑩(2010-6-27)作者信箱:wondersy0618@163.com刖言文章借助王爽老師編寫的Toyix操作系統(tǒng),通過對一個個程序的執(zhí)行結果的分析,向讀者演示了操作系統(tǒng)中進程的基本原理和基本特性。這篇文章面向已經(jīng)掌握c語言和數(shù)據(jù)結構的操作系統(tǒng)的初學者。讀者除了學習其中的知識,更應該學習體會文章中分析探索問題的方法,并在以后的計算機學習中應用這些方法。這些學習的能力是比知識更重要的東西。文章在編寫過程中參考了Toyix簡易教程,《計算機操作系統(tǒng)》(西安電子科技大學出版社),《匯編語言》(王爽)操作系統(tǒng)發(fā)展的意義在沒有出現(xiàn)操作系統(tǒng)以前,計算機只能在一段時間執(zhí)行一段程序,程序因為IO請求等原因發(fā)生阻塞時,CPU會處于空閑狀態(tài)造成資源的浪費。因為早期的計算機價格昂貴,用戶就希望可以更高效的利用計算機資源。這種需求就促進了操作系統(tǒng)的產(chǎn)生和發(fā)展。進程我們今天使用的操作系統(tǒng)主要是分時系統(tǒng),由調度程序調入的多個作業(yè)共享CPU資源,其中每個作業(yè)只執(zhí)行極短的一段時間(比如0.1S,我們稱為一個時間片),極短的時間過后暫停執(zhí)行,調入下一個程序。這樣在不長的一段時間內(比如5s內),有限的進程(少于50個)都可以得到至少一次的執(zhí)行,用戶請求可以得到及時的響應。這種作業(yè)調度的方式我們稱為時間片輪轉法。這種執(zhí)行的方式叫并發(fā)執(zhí)行,并發(fā)性也是分時系統(tǒng)的基本特性之一。在分時系統(tǒng)中,為了執(zhí)行一項作業(yè),就需要把要執(zhí)行的作業(yè)程序載入內存中作為程序段,為作業(yè)分配相應的數(shù)據(jù)空間作為數(shù)據(jù)段,并加入一個控制塊(PCB),用來保存當前作業(yè)執(zhí)行所必須的一些信息,使之能夠并發(fā)執(zhí)行。內存中的程序段、數(shù)據(jù)段和PCB我們稱為一個進程實體,而一個進程實體的執(zhí)行過程我們稱為進程。

進程的三種基本狀態(tài)我們已經(jīng)知道了進程實際是一個動態(tài)的概念,我們再回到分時系統(tǒng)的原理上。分時系統(tǒng)是給一個進程分配一個時間片,讓這個進程執(zhí)行,當進程時間片用完以后,為下一個進程分配時間片。當進程執(zhí)行過程中發(fā)生阻塞,則主動讓出CPU控制權,給其它進程執(zhí)行的機會。分析上面的過程,每一時刻只有一個進程處于執(zhí)行的狀態(tài)。而有多個進程處于等待分配時間片的狀態(tài),這多個進程應該遵循一定的順序。事實上是存在于一個隊列中。這種等待分配時間片的狀態(tài)我們稱為就緒狀態(tài),存放就緒進程的隊列就稱為就緒隊列。當CPU處于空閑狀態(tài)時,調度程序就會從就緒隊列中取出一個進程并執(zhí)行。當進程時間片用完后,調度信息就會把這個進程放入到就緒隊列中。除了時間片用完,當進程IO請求時,進程會在IO請求完畢之前無法繼續(xù)執(zhí)行,這類情況我們稱為進程的阻塞(可能出現(xiàn)進程阻塞的有IO請求,申請緩沖空間等)。當出現(xiàn)進程阻塞后,調度程序應該怎么處理呢?首先進程肯定不能放入就緒態(tài),因為放入就緒態(tài)就有可能被分配時間片,而此時進程不能繼續(xù)執(zhí)行,這就浪費了CPU資源。調度程序對其進行的處理是將其放到一個阻塞隊列中,當10完成時,再把它放回就緒隊列等待分配時間片。圖1進程就緒態(tài)、執(zhí)行態(tài)和阻塞態(tài)的關系圖1圖1進程就緒態(tài)、執(zhí)行態(tài)和阻塞態(tài)的關系使用Toyix查看進程的三種狀態(tài)Toyix是一個專門為操作系統(tǒng)的基礎理論教學而編寫的系統(tǒng),通過這個系統(tǒng)可以很方便的模擬進程的創(chuàng)建執(zhí)行過程。啟動toyix系統(tǒng),如圖從Toyix網(wǎng)站(/)下載系統(tǒng)并安裝(具體安裝方式請參考網(wǎng)站教程)啟動toyix系統(tǒng),如圖Toyix操作系統(tǒng)支持絕大部分常用的dos命令,我們可以使用dos下的編程方式進行編程??梢允褂胐os下的工具編寫程序源碼,如圖<Co->C:>edit1-c下面我們編寫一個程序,用來演示程序的三種狀態(tài)#include<toyix.h>main()(inti;for(i=0;i<80;i++)(put_str(3,i,2,"a");delay(30);}get_char();for(i=0;i<80;i++)(put_str(5,i,2,"b");delay(30);}分析上面的程序,程序中引入toyix庫toyix.h文件是為了使用toyix系統(tǒng)提供的關于的函數(shù)。程序首先在循環(huán)內調用put_str在屏幕第三行輸出字符a(關于put_str的用法,請參考toyix函數(shù)手冊),每輸出一次延時30ms。然后調用get_char函數(shù)阻塞式獲得用戶輸入。最后再通過一個循環(huán)在屏幕第五行輸出一行字符b。下面我們在toyix下編譯這個程序。toyix提供的c語言編譯命令是cc,使用方式是“ccc語言源文件文件名”,如圖<Co->C:>cc1-cCompiling...1.c:Auailablememovy208664Linking...Making...1-prg<Co.>C:>程序已經(jīng)編譯,連接成功,產(chǎn)生了toyix下的可執(zhí)行文件2.prg,prg是toyix下可執(zhí)行文件的后綴名。下面運行這個程序。Toyix中運行一個可執(zhí)行文件的命令是do,使用方法是“do可知性文件的文件名”,注意不需要加后綴名,如圖<Co.>C:>do1然后以后就看到了toyix程序運行時的界面blocked:ToyixMultiprocessMonitorU0.03

blocked:ToyixMultiprocessMonitorU0.03屏幕上邊的藍條是toyix進程監(jiān)視器,通過它我們可以方便的知道每個進程所處于的狀態(tài)。其中running后指示的是處于運行狀態(tài)的進程id,ready后指示的是處于就緒狀態(tài)的進程id,blocked指示的是處于阻塞狀態(tài)的進程id??梢钥吹轿覀兊某绦蛞呀?jīng)準備完畢,按任意鍵開始執(zhí)行。程序應該是處于就緒態(tài),進程id是1。而此時沒有更多的任務,CPU處于空閑狀態(tài),running處用一個紅色的0表示。按任意鍵開始執(zhí)行程序running:1ready: blocked: ToyixMultiprocessMonitoruO.S31.prgokHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa程序開始在屏幕輸出a,此時程序處于運行態(tài)。一行輸出完畢,程序會請求用戶輸入,如圖running:0ready: blocked:1 ToyixMultiprocessMonitorU0.031.prg<15ok可以看到ID為1的進程此時處于阻塞態(tài)。按任意鍵,使程序繼續(xù)執(zhí)行running:1ready: blocked: ToyixMultiprocessMonitoru0.031.prg<1>okaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb如圖,程序進入運行態(tài)繼續(xù)輸出字符b,知道程序運行結束。事實上,進程應該有一個進入就緒態(tài)的過程,再由操作系統(tǒng)取出就緒進程分配時間片后進入運行態(tài),但是因為時間太短(Toyix系統(tǒng)每個時間片大概是50ms),我們沒有看到那個狀態(tài)。進程與輕權進程我們已經(jīng)知道,操作系統(tǒng)的多個進程處于并發(fā)執(zhí)行的狀態(tài)。一個進程p1可以創(chuàng)建另一個進程p2,我們稱p2為p1的子進程,p1為p2的父進程。每個進程都會有一個進程實體,下面我們研究父進程與子進程進程實體之間的聯(lián)系我們可以應用c語言的某些特性來進行研究,比如我們可以通過下面的程序來輸出一個變量在內存中的位置#include<toyix.h>inti=0;main()(printf("\n%d:%d\n",_DS,&i);} —blocked:ToyixMultiprocessMonitoru0.03執(zhí)行后就得到了變量i的段地址和偏移地址(4324d:3216d)blocked:ToyixMultiprocessMonitoru0.03running:0ready4.prg<1>okPress key■■■4324:3216

也可以通過下面這段程序來打印main函數(shù)的地址#include<toyix.h>inti=0;main()(printf("\n%d:%d\n",_CS,main);} —blocked:ToyixMultiprocessMonitoru0.03執(zhí)行后獲得了main函數(shù)的段地址和偏移地址(4324d:0785dblocked:ToyixMultiprocessMonitoru0.03running:0ready4.prg<1>okPressemykey■■■4324:785通過以上兩種方法,我們可以得到一個進程的數(shù)據(jù)和代碼在內存中的位置。Toyix為我們提供了兩個簡單的創(chuàng)建進程的函數(shù)fork()和frk(),這兩個函數(shù)的調用方法我們不做具體介紹,請參考toyix的函數(shù)手冊。下面我們分別研究這兩個函數(shù)創(chuàng)建進程的差別。編寫下面的程序#include<toyix.h>inti=-1;main()(i=fork();printf("\n\n\nCallforkreturnvalueis%d\n",i);printf("\nPID=%d\n",get_pid());printf("\nFunctionmainoftheaddressis%d:%d\n",_CS,main);printf("\nVariableioftheaddressis%d:%d\n",_DS,&i);delay(500);}分析這個程序,這個程序調用fork()函數(shù)創(chuàng)建的新的進程,并在每個進程中輸出fork()函數(shù)返回值(判斷父進程還是子進程),當前進程ID,main函數(shù)的地址,變量i的地址。運行這個程序如圖,通過fork()函數(shù)的返回值我們判斷,pid為1的進程為父進程。而且父進程與子進程數(shù)據(jù)段和代碼段均不相同。這說明通過fork()函數(shù)創(chuàng)建的進程數(shù)據(jù)與代碼不共享。下面我們用同樣的方法研究通過frk()函數(shù)創(chuàng)建的進程,修改上面的程序#include<toyix.h>inti=-1;main()(i=frk();printf("\n\n\nCallforkreturnvalueis%d\n",i);printf("\nPID=%d\n",get_pid());printf("\nFunctionmainoftheaddressis%d:%d\n",_CS,main);printf("\nVariableioftheaddressis%d:%d\n",_DS,&i);delay(500);}這個程序與上面的程序基本相同,只是把fork()函數(shù)改為了frk()函數(shù),在toyix中運行這個程序我們發(fā)現(xiàn),pid為1的進程為父進程,父進程與子進程代碼段不同,但是數(shù)據(jù)段相同。這說明,通過frk()創(chuàng)建的進程數(shù)據(jù)段共享,代碼段不共享。這種進程我們稱為輕權進程。我們?yōu)槭裁匆獎?chuàng)建輕權進程呢?創(chuàng)建進程是為了提高系統(tǒng)資源利用率,但是因為進程擁有自己的數(shù)據(jù)段。進程的創(chuàng)建需要申請數(shù)據(jù)空間,銷毀需要釋放數(shù)據(jù)空間,切換進程需要保存并重新設置CPU寄存器現(xiàn)場。進程的創(chuàng)建,切換和銷毀都需要消耗大量的CPU資源。有時我們需要把自己的一個進程分成幾部分同時處理。比如程序中有一段代碼會循環(huán)等待用戶輸入,而用戶的是否輸入并不會影響我們程序的繼續(xù)運行,我們不希望等待用戶輸入時主程序也進入阻塞狀態(tài)。我們可以將用戶輸入的部分創(chuàng)建一個新的進程,但是事實上這個進程并不需要分配新的數(shù)據(jù)空間。那么就出現(xiàn)了沒有自己獨立的數(shù)據(jù)空間的進程,也就是輕權進程。輕權進程在創(chuàng)建,切換和銷毀時消耗的資源比進程都小的多。下面我們做這樣一個實驗。編寫下面的程序#include<toyix.h>main()(frk();printf("\nPID=%d\n",get_pid());} —程序中調用frk()創(chuàng)建輕權進程以后每個進程打印自己的進程id。在toyix下運行并查看結果running-prg<1>ressan</ID=10readyrunning-prg<1>ressan</ID=10readyokkey-..blockedToyixMultiprocessMonitoru0.可以看到運行結果與我們預想的不太一樣,只打印了一個進程的pid,另一個沒有打印。這是為什么呢?我們修改一下這個程序#include<toyix.h>main()(frk();printf("\nPID=%d\n",get_pid());delay(100);與前一個比較,這個程序多調用了一個延時功能。再看運行結果runn:0ready:okkey...blockedToyixMultiprocessMonitoru0.03runn:0ready:okkey...blockedToyixMultiprocessMonitoru0.03我們發(fā)現(xiàn)現(xiàn)在的顯示結果正確了?,F(xiàn)在為什么正確了呢?我們分析第一個程序,主進程創(chuàng)建進程以后,打印輸出自己的進程id。此時子進程還沒有得到執(zhí)行的機會,父進程就運行結束了,子進程也被銷毀。子進程雖然創(chuàng)建了,但是并沒有得到執(zhí)行。所以出現(xiàn)了錯誤的結果。第二個程序中,在父進程打印出自己的進程id以后,通過延時給子進程執(zhí)行的機會,子進程進入運行態(tài),打印子進程pid,輸出結果正常。以上分析表明,如果父進程結束,操作系統(tǒng)會銷毀它創(chuàng)建的所有輕權進程。這很容易理解,因為輕權進程是沒用數(shù)據(jù)空間的,它共享父進程的數(shù)據(jù)空間。而父進程銷毀時,數(shù)據(jù)空間會被釋放,此時如果子進程繼續(xù)執(zhí)行,可能訪問已經(jīng)釋放掉的空間,這是不安全的。這一部分我們講述了進程與輕權進程的一些差別。簡單來說,進程是可以獨立運行的最小單位。而輕權進程是可供操作系統(tǒng)調度的最小單位。后面我們要繼續(xù)講述怎樣在我們編寫的程序中更方便的創(chuàng)建多個輕權進程。使用cobegin創(chuàng)建輕權進程通過以上的學習我們知道,為了更高效的利用資源,我們編寫的程序可能要創(chuàng)建多個輕權進程。但是使用frk()創(chuàng)建的進程只能在兩個進程中執(zhí)行同一段代碼,這樣的進程是沒有實際意義的。為了方便的創(chuàng)建輕權進程,toyix為我們提供了cobegin函數(shù)。Toyix函數(shù)手冊中對這個函數(shù)的描述如下:原型:intcobegin();功能:創(chuàng)建多個子進程并發(fā)執(zhí)行函數(shù)參數(shù):函數(shù)名用0結束,例如:cobegin(f1,f2,f3,0);返回:創(chuàng)建子進程的個數(shù)說明:所有子進程共享數(shù)據(jù)段,主進程撤銷,所有子進程將被撤銷。我們編寫一個程序,通過cobigin函數(shù)來創(chuàng)建多個輕權進程。#include<toyix.h>voidf1()(printf("\nfunctionf1,pid=%d\n",get_pid());TOC\o"1-5"\h\z} —voidf2()(printf("\nfunctionf2,pid=%d\n",get_pid());} —voidf3()(printf("\nfunctionf3,pid=%d\n",get_pid());} —main()(printf("\nfunctionmain,pid=%d\n",get_pid());cobegin(f1,f2,f3,0);delay(100);}在這個程序中,main函數(shù)首先輸出自己的pid,然后調用cobegin函數(shù)將f1,f2,f3函數(shù)分別作為一個輕權進程運行,在每個輕權進程里,打印自己的函數(shù)名和pid。運行結果如圖多進程引發(fā)的問題下面我們要應用多進程技術編寫一個模擬火車售票系統(tǒng)的程序。在火車票售票中心的服務器上,保存著未售出的火車票數(shù)量。而各地有很多代售點,他們在售票時會連接到售票中心檢查火車票剩余情況,如果還有剩余票,那么賣出這張牌,同時通知售票中心車票被賣出。編寫程序實現(xiàn)這個過程,首先創(chuàng)建一個全局變量,用來保存剩余票數(shù)。編寫一個函數(shù)用來模擬一個售票窗口的售票流程。再通過在main函數(shù)中調用cobegin函數(shù)創(chuàng)建多個輕權進程,模擬多個窗口售票。程序代碼如下:

#include<toyix.h>inttotal=10;voidf1()(while(total>0)(delay(50);printf("\npid=%d,sellticket:%d",get_pid(),total--);} —}main()(cobegin(f1,f1,0);getch();}在單個窗口的售票流程中,首先檢查剩余票數(shù)是否大于0,如果大于0,那么延時一段時間(模擬真實情況),然后賣出這張票,再令剩余票減一。在toyix系統(tǒng)中運行,模擬結果如圖running:1ready:1.prg<1>okPressanyke</.--pid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketrunning:1ready:1.prg<1>okPressanyke</.--pid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticketpid=3,sellticketpid=2,sellticket019876543210blocked:ToyixMultiprocessMonitoruS.03我們發(fā)現(xiàn)一個問題,售票窗口售出了0號票,這在實際應用中是不允許的。為什么會發(fā)生這種情況呢?我們再分析剛才的程序,為了分析簡單,我們假設假如程序運行了一段時間,還有一張票未售出。程序中每個輕權進程的執(zhí)行過程如下圖所示。(虛線代表阻塞態(tài)或就緒態(tài),實現(xiàn)代表運行態(tài))total:total:主進程:主進程創(chuàng)建完輕權進程P1和P2后,在獲得用戶鍵盤輸入之前一直處于阻塞態(tài)沒有獲得時間片主進程:a)P1獲得時間片,檢測到total>0,進入售票程序延時一段時間,還未售票時間片已經(jīng)用完輕權進程P1:c)P1獲得時間片繼續(xù)運行,售票程序售出這張票后,令total減一。再次檢測total=0,循環(huán)結束,進程結束b)P2獲得時間片,與a中處理過程相同輕權進程P2: id)P2獲得時間片,售票后退出。但是此時total=0,所以售出了0號票此時一個進程(pid=2)檢查total的值,檢測到大于0進入售票程序,調用delay延時(注意票并沒有售出,tatal仍為1)。此時另一個輕權進程(pid=3)獲得了時間片開始運行,仍會檢測tatal的值,同樣進入了售票程序,調用delay延時。調度程序調出剛才的輕權進程(pid=2)的進程繼續(xù)執(zhí)行,售出1號票并將票數(shù)減1,再次檢測tatal小于0,pid為2的輕權進程結束退出。Pid為3的輕權進程回到剛才的狀態(tài)繼續(xù)售票,而此時tatal為0,所以售出了0號票。顯然,在這個實驗中如果沒有延時操作,可能不會出現(xiàn)這樣的情況。但是在一個長期運行的多個輕權進程的系統(tǒng)中,很有可能出現(xiàn)這種兩個輕權進程訪問同一資源時出錯的問題。增加一個延時只是放大了這種問題。通過上述分析,我們了解了一個進程通過創(chuàng)建多個輕權進程雖然可以提高資源的利用率,但是在訪問同一資源時可能引起一些問題。為了解決這些問題,我們必須在不同輕權進程訪問同一資源時進行一些判

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論