进程初识和multiprocessing模块之Process
生活随笔
收集整理的這篇文章主要介紹了
进程初识和multiprocessing模块之Process
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、什么是進(jìn)程
進(jìn)程就是運行中的程序進(jìn)程是操作系統(tǒng)中最小的資源分配單位進(jìn)程與進(jìn)程之間的關(guān)系 : 數(shù)據(jù)隔離的進(jìn)程的id:Process id = pid
pid是一個全系統(tǒng)唯一的對某個進(jìn)程的標(biāo)識,隨著這個進(jìn)程的重啟pid可能會變化
程序與進(jìn)程的區(qū)別
程序是指令和數(shù)據(jù)的有序集合,其本身沒有任何運行的含義,是一個靜態(tài)的概念。 而進(jìn)程是程序在處理機上的一次執(zhí)行過程,它是一個動態(tài)的概念。 程序可以作為一種軟件資料長期存在,而進(jìn)程是有一定生命期的。 程序是永久的,進(jìn)程是暫時的。 進(jìn)程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。在早期面向進(jìn)程設(shè)計的計算機結(jié)構(gòu)中,進(jìn)程是程序的基本執(zhí)行實體;在當(dāng)代面向線程設(shè)計的計算機結(jié)構(gòu)中,進(jìn)程是線程的容器。程序是指令、數(shù)據(jù)及其組織形式的描述,進(jìn)程是程序的實體。狹義定義:進(jìn)程是正在運行的程序的實例(an instance of a computer program that is being executed)。 廣義定義:進(jìn)程是一個具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合的一次運行活動。它是操作系統(tǒng)動態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元。 進(jìn)程 第一,進(jìn)程是一個實體。每一個進(jìn)程都有它自己的地址空間,一般情況下,包括文本區(qū)域(text region)、數(shù)據(jù)區(qū)域(data region)和堆棧(stack region)。文本區(qū)域存儲處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲變量和進(jìn)程執(zhí)行期間使用的動態(tài)分配的內(nèi)存;堆棧區(qū)域存儲著活動過程調(diào)用的指令和本地變量。 第二,進(jìn)程是一個“執(zhí)行中的程序”。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操作系統(tǒng)執(zhí)行之),它才能成為一個活動的實體,我們稱其為進(jìn)程。[3] 進(jìn)程是操作系統(tǒng)中最基本、重要的概念。是多道程序系統(tǒng)出現(xiàn)后,為了刻畫系統(tǒng)內(nèi)部出現(xiàn)的動態(tài)情況,描述系統(tǒng)內(nèi)部各道程序的活動規(guī)律引進(jìn)的一個概念,所有多道程序設(shè)計操作系統(tǒng)都建立在進(jìn)程的基礎(chǔ)上。 概念 動態(tài)性:進(jìn)程的實質(zhì)是程序在多道程序系統(tǒng)中的一次執(zhí)行過程,進(jìn)程是動態(tài)產(chǎn)生,動態(tài)消亡的。 并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行 獨立性:進(jìn)程是一個能獨立運行的基本單位,同時也是系統(tǒng)分配資源和調(diào)度的獨立單位; 異步性:由于進(jìn)程間的相互制約,使進(jìn)程具有執(zhí)行的間斷性,即進(jìn)程按各自獨立的、不可預(yù)知的速度向前推進(jìn) 結(jié)構(gòu)特征:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。 多個不同的進(jìn)程可以包含相同的程序:一個程序在不同的數(shù)據(jù)集里就構(gòu)成不同的進(jìn)程,能得到不同的結(jié)果;但是執(zhí)行過程中,程序不能發(fā)生改變。 特征
二、進(jìn)程的調(diào)度
要想多個進(jìn)程交替運行,操作系統(tǒng)必須對這些進(jìn)程進(jìn)行調(diào)度,這個調(diào)度也不是隨即進(jìn)行的,而是需要遵循一定的法則,由此就有了進(jìn)程的調(diào)度算法。
1、先來先服務(wù)
先來先服務(wù)(FCFS)調(diào)度算法是一種最簡單的調(diào)度算法,該算法既可用于作業(yè)調(diào)度,也可用于進(jìn)程調(diào)度。FCFS算法比較有利于長作業(yè)(進(jìn)程),而不利于短作業(yè)(進(jìn)程)。
由此可知,本算法適合于CPU繁忙型作業(yè),而不利于I/O繁忙型的作業(yè)(進(jìn)程)。 2、短作業(yè)優(yōu)先
短作業(yè)(進(jìn)程)優(yōu)先調(diào)度算法(SJ/PF)是指對短作業(yè)或短進(jìn)程優(yōu)先調(diào)度的算法,該算法既可用于作業(yè)調(diào)度,也可用于進(jìn)程調(diào)度。但其對長作業(yè)不利;不能保證緊迫性作業(yè)(進(jìn)程)被及時處理;
作業(yè)的長短只是被估算出來的。
3、時間片輪轉(zhuǎn)法
時間片輪轉(zhuǎn)(Round Robin,RR)法的基本思路是讓每個進(jìn)程在就緒隊列中的等待時間與享受服務(wù)的時間成比例。在時間片輪轉(zhuǎn)法中,需要將CPU的處理時間分成固定大小的時間片,
例如,幾十毫秒至幾百毫秒。如果一個進(jìn)程在被調(diào)度選中之后用完了系統(tǒng)規(guī)定的時間片,但又未完成要求的任務(wù),則它自行釋放自己所占有的CPU而排到就緒隊列的末尾,等待下一次調(diào)度。
同時,進(jìn)程調(diào)度程序又去調(diào)度當(dāng)前就緒隊列中的第一個進(jìn)程。 4、多級反饋隊列
前面介紹的各種用作進(jìn)程調(diào)度的算法都有一定的局限性。如短進(jìn)程優(yōu)先的調(diào)度算法,僅照顧了短進(jìn)程而忽略了長進(jìn)程,而且如果并未指明進(jìn)程的長度,則短進(jìn)程優(yōu)先和基于進(jìn)程長度的搶占式調(diào)度算法都將無法使用。而多級反饋隊列調(diào)度算法則不必事先知道各種進(jìn)程所需的執(zhí)行時間,而且還可以滿足各種類型進(jìn)程的需要,因而它是目前被公認(rèn)的一種較好的進(jìn)程調(diào)度算法。在采用多級反饋隊列調(diào)度算法的系統(tǒng)中,調(diào)度算法的實施過程如下所述。 (1) 應(yīng)設(shè)置多個就緒隊列,并為各個隊列賦予不同的優(yōu)先級。第一個隊列的優(yōu)先級最高,第二個隊列次之,其余各隊列的優(yōu)先權(quán)逐個降低。該算法賦予各個隊列中進(jìn)程執(zhí)行時間片的大小也各不相同,在優(yōu)先權(quán)愈高的隊列中,為每個進(jìn)程所規(guī)定的執(zhí)行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。 (2) 當(dāng)一個新進(jìn)程進(jìn)入內(nèi)存后,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調(diào)度。當(dāng)輪到該進(jìn)程執(zhí)行時,如它能在該時間片內(nèi)完成,便可準(zhǔn)備撤離系統(tǒng);如果它在一個時間片結(jié)束時尚未完成,調(diào)度程序便將該進(jìn)程轉(zhuǎn)入第二隊列的末尾,再同樣地按FCFS原則等待調(diào)度執(zhí)行;如果它在第二隊列中運行一個時間片后仍未完成,再依次將它放入第三隊列,……,如此下去,當(dāng)一個長作業(yè)(進(jìn)程)從第一隊列依次降到第n隊列后,在第n 隊列便采取按時間片輪轉(zhuǎn)的方式運行。 (3) 僅當(dāng)?shù)谝魂犃锌臻e時,調(diào)度程序才調(diào)度第二隊列中的進(jìn)程運行;僅當(dāng)?shù)?~(i-1)隊列均空時,才會調(diào)度第i隊列中的進(jìn)程運行。如果處理機正在第i隊列中為某進(jìn)程服務(wù)時,又有新進(jìn)程進(jìn)入優(yōu)先權(quán)較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進(jìn)程將搶占正在運行進(jìn)程的處理機,即由調(diào)度程序把正在運行的進(jìn)程放回到第i隊列的末尾,把處理機分配給新到的高優(yōu)先權(quán)進(jìn)程。
三、進(jìn)程的并行與并發(fā)
并行?:?并行是指兩者同時執(zhí)行,比如賽跑,兩個人都在不停的往前跑;(資源夠用,比如三個線程,四核的CPU )
并發(fā)?:?并發(fā)是指資源有限的情況下,在一個時間段內(nèi)兩者交替輪流使用資源,比如一個單核CPU資源一次只能給一個進(jìn)程使用,A使用一段時間后,讓給B,B用完繼續(xù)給A ,交替使用,目的是提高效率。
區(qū)別:
并行是從微觀上,也就是在一個精確的時間片刻,有不同的程序在執(zhí)行,這就要求必須有多個處理器。
并發(fā)是從宏觀上,在一個時間段上可以看出是同時執(zhí)行的,比如一個服務(wù)器同時處理多個session。
四、同步異步阻塞非阻塞
1、三狀態(tài)介紹:
在程序運行的過程中,由于被操作系統(tǒng)的調(diào)度算法控制,程序會進(jìn)入幾個狀態(tài):就緒,運行和阻塞。
1、就緒(Ready)狀態(tài)
當(dāng)進(jìn)程已分配到除CPU以外的所有必要的資源,只要獲得CPU便可立即執(zhí)行,這時的進(jìn)程狀態(tài)稱為就緒狀態(tài)。
2、執(zhí)行/運行(Running)狀態(tài)
當(dāng)進(jìn)程已獲得處理器,其程序正在處理器上執(zhí)行,此時的進(jìn)程狀態(tài)稱為執(zhí)行狀態(tài)。
3、阻塞(Blocked)狀態(tài)
正在執(zhí)行的進(jìn)程,由于等待某個事件發(fā)生而無法執(zhí)行時,便放棄處理器而進(jìn)入阻塞狀態(tài)。引起進(jìn)程阻塞的事件可有多種,例如,等待I/O完成、申請緩沖區(qū)不能滿足、等待信件(信號)等。
2、同步異步
同步:兩件事 一件做完了再去做另一件事兒
例如:我先去洗衣服(手洗),洗完衣服再去做飯
異步:兩件事情同時做
例如:我有洗衣機了,我可以打開洗衣機,在洗衣機洗衣服的時候,我去做飯
3、阻塞和非阻塞
阻塞:例如socket編程中,服務(wù)端使用accept,就是阻塞,它會在那里一直等待客戶端來連接它
比如:你在洗衣服的時候沒有洗衣粉,等待洗衣粉而停止。
非阻塞:例如socket編程中,服務(wù)端對象使用setblocking(True),在accept的時候不會進(jìn)行等待,而是繼續(xù)向下運行
比如:有洗衣粉了,可以直接洗衣粉
同步阻塞 :不能充分利用CPU(效率最低)
比如:你在洗衣服的時候,沒有洗衣粉了,等待洗衣粉而停止,有洗衣粉后,洗完衣服了,然后去做飯,又沒有米了,等待米而停止
異步非阻塞 : 過度利用CPU(效率很高)
比如:你在洗衣服的時候,沒有洗衣粉了,但是你不停止,而是直接開洗衣機洗衣服,同時在做飯的時候,又沒有米了,你也直接煮
五、進(jìn)程的創(chuàng)建與結(jié)束
創(chuàng)建
而對于通用系統(tǒng)(跑很多應(yīng)用程序),需要有系統(tǒng)運行過程中創(chuàng)建或撤銷進(jìn)程的能力,主要分為4中形式創(chuàng)建新的進(jìn)程:
1. 系統(tǒng)初始化
2. 一個進(jìn)程在運行過程中開啟了子進(jìn)程
3. 用戶的交互式請求,而創(chuàng)建一個新進(jìn)程(如用戶QQ)
4. 一個批處理作業(yè)的初始化(只在大型機的批處理系統(tǒng)中應(yīng)用)
無論哪一種,新進(jìn)程的創(chuàng)建都是由一個已經(jīng)存在的進(jìn)程執(zhí)行了一個用于創(chuàng)建進(jìn)程的系統(tǒng)調(diào)用而創(chuàng)建的?!?
結(jié)束
1. 正常退出(自愿,如用戶點擊交互式頁面的叉號,或程序執(zhí)行完畢調(diào)用發(fā)起系統(tǒng)調(diào)用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出錯退出(自愿,python a.py中a.py不存在)
3. 嚴(yán)重錯誤(非自愿,執(zhí)行非法指令,如引用不存在的內(nèi)存,1/0等,可以捕捉異常,try...except...)
4. 被其他進(jìn)程殺死(非自愿)
六、multiprocessing模塊
1、模塊介紹
Process模塊是一個創(chuàng)建進(jìn)程的模塊,借助這個模塊,就可以完成進(jìn)程的創(chuàng)建。 Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化得到的對象,表示一個子進(jìn)程中的任務(wù)(尚未啟動)強調(diào): 1. 需要使用關(guān)鍵字的方式來指定參數(shù) 2. args指定的為傳給target函數(shù)的位置參數(shù),是一個元組形式,必須有逗號參數(shù)介紹: 1 group參數(shù)未使用,值始終為None 2 target表示調(diào)用對象,即子進(jìn)程要執(zhí)行的任務(wù) 3 args表示調(diào)用對象的位置參數(shù)元組,args=(1,2,'a',) 4 kwargs表示調(diào)用對象的字典,kwargs={'name':'ming','age':18} 5 name為子進(jìn)程的名稱 ? 方法介紹
1、 p.start():啟動進(jìn)程,并調(diào)用該子進(jìn)程中的p.run() 2、 p.run():進(jìn)程啟動時運行的方法,正是它去調(diào)用target指定的函數(shù),我們自定義類的類中一定要實現(xiàn)該方法 3、 p.terminate():強制終止進(jìn)程p,不會進(jìn)行任何清理操作,如果p創(chuàng)建了子進(jìn)程,該子進(jìn)程就成了僵尸進(jìn)程,使用該方法需要特別小心這種情況。如果p還保存了一個鎖那么也將不會被釋放,進(jìn)而導(dǎo)致死鎖 4、 p.is_alive():如果p仍然運行,返回True 5、 p.join([timeout]):主線程等待p終止(強調(diào):是主線程處于等的狀態(tài),而p是處于運行的狀態(tài))。timeout是可選的超時時間,需要強調(diào)的是,p.join只能join住start開啟的進(jìn)程,而不能join住run開啟的進(jìn)程
屬性介紹
1、 p.daemon:默認(rèn)值為False,如果設(shè)為True,代表p為后臺運行的守護(hù)進(jìn)程,當(dāng)p的父進(jìn)程終止時,p也隨之終止,并且設(shè)定為True后,p不能創(chuàng)建自己的新進(jìn)程,必須在p.start()之前設(shè)置 2、 p.name:進(jìn)程的名稱 3、 p.pid:進(jìn)程的pid
4、 p.exitcode:進(jìn)程在運行時為None、如果為–N,表示被信號N結(jié)束(了解即可) 5、 p.authkey:進(jìn)程的身份驗證鍵,默認(rèn)是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是為涉及網(wǎng)絡(luò)連接的底層進(jìn)程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)
在windows中使用需要注意
在Windows操作系統(tǒng)中由于沒有fork(linux操作系統(tǒng)中創(chuàng)建進(jìn)程的機制),在創(chuàng)建子進(jìn)程的時候會自動 import 啟動它的這個文件,而在 import 的時候又執(zhí)行了整個文件。因此如果將process()直接寫在文件中就會無限遞歸創(chuàng)建子進(jìn)程報錯。
所以必須把創(chuàng)建子進(jìn)程的部分使用if __name__ =='__main__' 判斷保護(hù)起來,import 的時候 ,就不會遞歸運行了。
例子:
1、 import os import time from multiprocessing import Process def func(arg):time.sleep(0.5)print('子進(jìn)程%s,子進(jìn)程id:%s,父進(jìn)程id:%s'%(arg,os.getpid(),os.getppid())) # os.getpid當(dāng)前進(jìn)程id,os.getppid父進(jìn)程id 注意與屬性p.pid的區(qū)分if __name__ == '__main__':p = Process(target=func,args=(1,)) # 實例化一個進(jìn)程,Process是一個類 p.start()print('主進(jìn)程id:%s,主進(jìn)程的父進(jìn)程id:%s,子進(jìn)程id:%s' % (os.getpid(), os.getppid(), p.pid)) 2、數(shù)據(jù)隔離 import os from multiprocessing import Process count = 100 def func():global countcount -= 1print('子進(jìn)程:',count)if __name__ == '__main__':print('主進(jìn)程',os.getpid(),os.getppid())p = Process(target=func)p.start()print('主進(jìn)程:',count)結(jié)果: 主進(jìn)程 8316 5512 主進(jìn)程: 100 子進(jìn)程: 99
3、啟動多個子進(jìn)程(子進(jìn)程的執(zhí)行順序不是根據(jù)啟動順序決定的) import os from multiprocessing import Process def func(arg):print('子進(jìn)程%s :'%arg ,os.getpid(),os.getppid())if __name__ == '__main__':for i in range(10):Process(target=func,args=(i,)).start() 4、子進(jìn)程和父進(jìn)程之間的關(guān)系 1.父進(jìn)程和子進(jìn)程的啟動是異步的 父進(jìn)程只負(fù)責(zé)通知操作系統(tǒng)啟動子進(jìn)程 接下來的工作由操作系統(tǒng)接手 父進(jìn)程繼續(xù)執(zhí)行自己的代碼2.父進(jìn)程執(zhí)行完畢之后并不會直接結(jié)束程序, 而是會等待所有的子進(jìn)程都執(zhí)行完畢之后才結(jié)束 父進(jìn)程要負(fù)責(zé)回收子進(jìn)程的資源import time import os from multiprocessing import Process def func(arg):print('子進(jìn)程%s :'%arg ,os.getpid(),os.getppid())time.sleep(5)print('子進(jìn)程end')if __name__ == '__main__':for i in range(10):Process(target=func,args=(i,)).start()print('父進(jìn)程。。。')
程序與進(jìn)程的區(qū)別
程序是指令和數(shù)據(jù)的有序集合,其本身沒有任何運行的含義,是一個靜態(tài)的概念。 而進(jìn)程是程序在處理機上的一次執(zhí)行過程,它是一個動態(tài)的概念。 程序可以作為一種軟件資料長期存在,而進(jìn)程是有一定生命期的。 程序是永久的,進(jìn)程是暫時的。 進(jìn)程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。在早期面向進(jìn)程設(shè)計的計算機結(jié)構(gòu)中,進(jìn)程是程序的基本執(zhí)行實體;在當(dāng)代面向線程設(shè)計的計算機結(jié)構(gòu)中,進(jìn)程是線程的容器。程序是指令、數(shù)據(jù)及其組織形式的描述,進(jìn)程是程序的實體。狹義定義:進(jìn)程是正在運行的程序的實例(an instance of a computer program that is being executed)。 廣義定義:進(jìn)程是一個具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合的一次運行活動。它是操作系統(tǒng)動態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元。 進(jìn)程 第一,進(jìn)程是一個實體。每一個進(jìn)程都有它自己的地址空間,一般情況下,包括文本區(qū)域(text region)、數(shù)據(jù)區(qū)域(data region)和堆棧(stack region)。文本區(qū)域存儲處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲變量和進(jìn)程執(zhí)行期間使用的動態(tài)分配的內(nèi)存;堆棧區(qū)域存儲著活動過程調(diào)用的指令和本地變量。 第二,進(jìn)程是一個“執(zhí)行中的程序”。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操作系統(tǒng)執(zhí)行之),它才能成為一個活動的實體,我們稱其為進(jìn)程。[3] 進(jìn)程是操作系統(tǒng)中最基本、重要的概念。是多道程序系統(tǒng)出現(xiàn)后,為了刻畫系統(tǒng)內(nèi)部出現(xiàn)的動態(tài)情況,描述系統(tǒng)內(nèi)部各道程序的活動規(guī)律引進(jìn)的一個概念,所有多道程序設(shè)計操作系統(tǒng)都建立在進(jìn)程的基礎(chǔ)上。 概念 動態(tài)性:進(jìn)程的實質(zhì)是程序在多道程序系統(tǒng)中的一次執(zhí)行過程,進(jìn)程是動態(tài)產(chǎn)生,動態(tài)消亡的。 并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行 獨立性:進(jìn)程是一個能獨立運行的基本單位,同時也是系統(tǒng)分配資源和調(diào)度的獨立單位; 異步性:由于進(jìn)程間的相互制約,使進(jìn)程具有執(zhí)行的間斷性,即進(jìn)程按各自獨立的、不可預(yù)知的速度向前推進(jìn) 結(jié)構(gòu)特征:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。 多個不同的進(jìn)程可以包含相同的程序:一個程序在不同的數(shù)據(jù)集里就構(gòu)成不同的進(jìn)程,能得到不同的結(jié)果;但是執(zhí)行過程中,程序不能發(fā)生改變。 特征
二、進(jìn)程的調(diào)度
要想多個進(jìn)程交替運行,操作系統(tǒng)必須對這些進(jìn)程進(jìn)行調(diào)度,這個調(diào)度也不是隨即進(jìn)行的,而是需要遵循一定的法則,由此就有了進(jìn)程的調(diào)度算法。
1、先來先服務(wù)
先來先服務(wù)(FCFS)調(diào)度算法是一種最簡單的調(diào)度算法,該算法既可用于作業(yè)調(diào)度,也可用于進(jìn)程調(diào)度。FCFS算法比較有利于長作業(yè)(進(jìn)程),而不利于短作業(yè)(進(jìn)程)。
由此可知,本算法適合于CPU繁忙型作業(yè),而不利于I/O繁忙型的作業(yè)(進(jìn)程)。 2、短作業(yè)優(yōu)先
短作業(yè)(進(jìn)程)優(yōu)先調(diào)度算法(SJ/PF)是指對短作業(yè)或短進(jìn)程優(yōu)先調(diào)度的算法,該算法既可用于作業(yè)調(diào)度,也可用于進(jìn)程調(diào)度。但其對長作業(yè)不利;不能保證緊迫性作業(yè)(進(jìn)程)被及時處理;
作業(yè)的長短只是被估算出來的。
3、時間片輪轉(zhuǎn)法
時間片輪轉(zhuǎn)(Round Robin,RR)法的基本思路是讓每個進(jìn)程在就緒隊列中的等待時間與享受服務(wù)的時間成比例。在時間片輪轉(zhuǎn)法中,需要將CPU的處理時間分成固定大小的時間片,
例如,幾十毫秒至幾百毫秒。如果一個進(jìn)程在被調(diào)度選中之后用完了系統(tǒng)規(guī)定的時間片,但又未完成要求的任務(wù),則它自行釋放自己所占有的CPU而排到就緒隊列的末尾,等待下一次調(diào)度。
同時,進(jìn)程調(diào)度程序又去調(diào)度當(dāng)前就緒隊列中的第一個進(jìn)程。 4、多級反饋隊列
前面介紹的各種用作進(jìn)程調(diào)度的算法都有一定的局限性。如短進(jìn)程優(yōu)先的調(diào)度算法,僅照顧了短進(jìn)程而忽略了長進(jìn)程,而且如果并未指明進(jìn)程的長度,則短進(jìn)程優(yōu)先和基于進(jìn)程長度的搶占式調(diào)度算法都將無法使用。而多級反饋隊列調(diào)度算法則不必事先知道各種進(jìn)程所需的執(zhí)行時間,而且還可以滿足各種類型進(jìn)程的需要,因而它是目前被公認(rèn)的一種較好的進(jìn)程調(diào)度算法。在采用多級反饋隊列調(diào)度算法的系統(tǒng)中,調(diào)度算法的實施過程如下所述。 (1) 應(yīng)設(shè)置多個就緒隊列,并為各個隊列賦予不同的優(yōu)先級。第一個隊列的優(yōu)先級最高,第二個隊列次之,其余各隊列的優(yōu)先權(quán)逐個降低。該算法賦予各個隊列中進(jìn)程執(zhí)行時間片的大小也各不相同,在優(yōu)先權(quán)愈高的隊列中,為每個進(jìn)程所規(guī)定的執(zhí)行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。 (2) 當(dāng)一個新進(jìn)程進(jìn)入內(nèi)存后,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調(diào)度。當(dāng)輪到該進(jìn)程執(zhí)行時,如它能在該時間片內(nèi)完成,便可準(zhǔn)備撤離系統(tǒng);如果它在一個時間片結(jié)束時尚未完成,調(diào)度程序便將該進(jìn)程轉(zhuǎn)入第二隊列的末尾,再同樣地按FCFS原則等待調(diào)度執(zhí)行;如果它在第二隊列中運行一個時間片后仍未完成,再依次將它放入第三隊列,……,如此下去,當(dāng)一個長作業(yè)(進(jìn)程)從第一隊列依次降到第n隊列后,在第n 隊列便采取按時間片輪轉(zhuǎn)的方式運行。 (3) 僅當(dāng)?shù)谝魂犃锌臻e時,調(diào)度程序才調(diào)度第二隊列中的進(jìn)程運行;僅當(dāng)?shù)?~(i-1)隊列均空時,才會調(diào)度第i隊列中的進(jìn)程運行。如果處理機正在第i隊列中為某進(jìn)程服務(wù)時,又有新進(jìn)程進(jìn)入優(yōu)先權(quán)較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進(jìn)程將搶占正在運行進(jìn)程的處理機,即由調(diào)度程序把正在運行的進(jìn)程放回到第i隊列的末尾,把處理機分配給新到的高優(yōu)先權(quán)進(jìn)程。
三、進(jìn)程的并行與并發(fā)
并行?:?并行是指兩者同時執(zhí)行,比如賽跑,兩個人都在不停的往前跑;(資源夠用,比如三個線程,四核的CPU )
并發(fā)?:?并發(fā)是指資源有限的情況下,在一個時間段內(nèi)兩者交替輪流使用資源,比如一個單核CPU資源一次只能給一個進(jìn)程使用,A使用一段時間后,讓給B,B用完繼續(xù)給A ,交替使用,目的是提高效率。
區(qū)別:
并行是從微觀上,也就是在一個精確的時間片刻,有不同的程序在執(zhí)行,這就要求必須有多個處理器。
并發(fā)是從宏觀上,在一個時間段上可以看出是同時執(zhí)行的,比如一個服務(wù)器同時處理多個session。
四、同步異步阻塞非阻塞
1、三狀態(tài)介紹:
在程序運行的過程中,由于被操作系統(tǒng)的調(diào)度算法控制,程序會進(jìn)入幾個狀態(tài):就緒,運行和阻塞。
1、就緒(Ready)狀態(tài)
當(dāng)進(jìn)程已分配到除CPU以外的所有必要的資源,只要獲得CPU便可立即執(zhí)行,這時的進(jìn)程狀態(tài)稱為就緒狀態(tài)。
2、執(zhí)行/運行(Running)狀態(tài)
當(dāng)進(jìn)程已獲得處理器,其程序正在處理器上執(zhí)行,此時的進(jìn)程狀態(tài)稱為執(zhí)行狀態(tài)。
3、阻塞(Blocked)狀態(tài)
正在執(zhí)行的進(jìn)程,由于等待某個事件發(fā)生而無法執(zhí)行時,便放棄處理器而進(jìn)入阻塞狀態(tài)。引起進(jìn)程阻塞的事件可有多種,例如,等待I/O完成、申請緩沖區(qū)不能滿足、等待信件(信號)等。
2、同步異步
同步:兩件事 一件做完了再去做另一件事兒
例如:我先去洗衣服(手洗),洗完衣服再去做飯
異步:兩件事情同時做
例如:我有洗衣機了,我可以打開洗衣機,在洗衣機洗衣服的時候,我去做飯
3、阻塞和非阻塞
阻塞:例如socket編程中,服務(wù)端使用accept,就是阻塞,它會在那里一直等待客戶端來連接它
比如:你在洗衣服的時候沒有洗衣粉,等待洗衣粉而停止。
非阻塞:例如socket編程中,服務(wù)端對象使用setblocking(True),在accept的時候不會進(jìn)行等待,而是繼續(xù)向下運行
比如:有洗衣粉了,可以直接洗衣粉
同步阻塞 :不能充分利用CPU(效率最低)
比如:你在洗衣服的時候,沒有洗衣粉了,等待洗衣粉而停止,有洗衣粉后,洗完衣服了,然后去做飯,又沒有米了,等待米而停止
異步非阻塞 : 過度利用CPU(效率很高)
比如:你在洗衣服的時候,沒有洗衣粉了,但是你不停止,而是直接開洗衣機洗衣服,同時在做飯的時候,又沒有米了,你也直接煮
五、進(jìn)程的創(chuàng)建與結(jié)束
創(chuàng)建
而對于通用系統(tǒng)(跑很多應(yīng)用程序),需要有系統(tǒng)運行過程中創(chuàng)建或撤銷進(jìn)程的能力,主要分為4中形式創(chuàng)建新的進(jìn)程:
1. 系統(tǒng)初始化
2. 一個進(jìn)程在運行過程中開啟了子進(jìn)程
3. 用戶的交互式請求,而創(chuàng)建一個新進(jìn)程(如用戶QQ)
4. 一個批處理作業(yè)的初始化(只在大型機的批處理系統(tǒng)中應(yīng)用)
無論哪一種,新進(jìn)程的創(chuàng)建都是由一個已經(jīng)存在的進(jìn)程執(zhí)行了一個用于創(chuàng)建進(jìn)程的系統(tǒng)調(diào)用而創(chuàng)建的?!?
結(jié)束
1. 正常退出(自愿,如用戶點擊交互式頁面的叉號,或程序執(zhí)行完畢調(diào)用發(fā)起系統(tǒng)調(diào)用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出錯退出(自愿,python a.py中a.py不存在)
3. 嚴(yán)重錯誤(非自愿,執(zhí)行非法指令,如引用不存在的內(nèi)存,1/0等,可以捕捉異常,try...except...)
4. 被其他進(jìn)程殺死(非自愿)
六、multiprocessing模塊
1、模塊介紹
Process模塊是一個創(chuàng)建進(jìn)程的模塊,借助這個模塊,就可以完成進(jìn)程的創(chuàng)建。 Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化得到的對象,表示一個子進(jìn)程中的任務(wù)(尚未啟動)強調(diào): 1. 需要使用關(guān)鍵字的方式來指定參數(shù) 2. args指定的為傳給target函數(shù)的位置參數(shù),是一個元組形式,必須有逗號參數(shù)介紹: 1 group參數(shù)未使用,值始終為None 2 target表示調(diào)用對象,即子進(jìn)程要執(zhí)行的任務(wù) 3 args表示調(diào)用對象的位置參數(shù)元組,args=(1,2,'a',) 4 kwargs表示調(diào)用對象的字典,kwargs={'name':'ming','age':18} 5 name為子進(jìn)程的名稱 ? 方法介紹
1、 p.start():啟動進(jìn)程,并調(diào)用該子進(jìn)程中的p.run() 2、 p.run():進(jìn)程啟動時運行的方法,正是它去調(diào)用target指定的函數(shù),我們自定義類的類中一定要實現(xiàn)該方法 3、 p.terminate():強制終止進(jìn)程p,不會進(jìn)行任何清理操作,如果p創(chuàng)建了子進(jìn)程,該子進(jìn)程就成了僵尸進(jìn)程,使用該方法需要特別小心這種情況。如果p還保存了一個鎖那么也將不會被釋放,進(jìn)而導(dǎo)致死鎖 4、 p.is_alive():如果p仍然運行,返回True 5、 p.join([timeout]):主線程等待p終止(強調(diào):是主線程處于等的狀態(tài),而p是處于運行的狀態(tài))。timeout是可選的超時時間,需要強調(diào)的是,p.join只能join住start開啟的進(jìn)程,而不能join住run開啟的進(jìn)程
屬性介紹
1、 p.daemon:默認(rèn)值為False,如果設(shè)為True,代表p為后臺運行的守護(hù)進(jìn)程,當(dāng)p的父進(jìn)程終止時,p也隨之終止,并且設(shè)定為True后,p不能創(chuàng)建自己的新進(jìn)程,必須在p.start()之前設(shè)置 2、 p.name:進(jìn)程的名稱 3、 p.pid:進(jìn)程的pid
4、 p.exitcode:進(jìn)程在運行時為None、如果為–N,表示被信號N結(jié)束(了解即可) 5、 p.authkey:進(jìn)程的身份驗證鍵,默認(rèn)是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是為涉及網(wǎng)絡(luò)連接的底層進(jìn)程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)
在windows中使用需要注意
在Windows操作系統(tǒng)中由于沒有fork(linux操作系統(tǒng)中創(chuàng)建進(jìn)程的機制),在創(chuàng)建子進(jìn)程的時候會自動 import 啟動它的這個文件,而在 import 的時候又執(zhí)行了整個文件。因此如果將process()直接寫在文件中就會無限遞歸創(chuàng)建子進(jìn)程報錯。
所以必須把創(chuàng)建子進(jìn)程的部分使用if __name__ =='__main__' 判斷保護(hù)起來,import 的時候 ,就不會遞歸運行了。
例子:
1、 import os import time from multiprocessing import Process def func(arg):time.sleep(0.5)print('子進(jìn)程%s,子進(jìn)程id:%s,父進(jìn)程id:%s'%(arg,os.getpid(),os.getppid())) # os.getpid當(dāng)前進(jìn)程id,os.getppid父進(jìn)程id 注意與屬性p.pid的區(qū)分if __name__ == '__main__':p = Process(target=func,args=(1,)) # 實例化一個進(jìn)程,Process是一個類 p.start()print('主進(jìn)程id:%s,主進(jìn)程的父進(jìn)程id:%s,子進(jìn)程id:%s' % (os.getpid(), os.getppid(), p.pid)) 2、數(shù)據(jù)隔離 import os from multiprocessing import Process count = 100 def func():global countcount -= 1print('子進(jìn)程:',count)if __name__ == '__main__':print('主進(jìn)程',os.getpid(),os.getppid())p = Process(target=func)p.start()print('主進(jìn)程:',count)結(jié)果: 主進(jìn)程 8316 5512 主進(jìn)程: 100 子進(jìn)程: 99
3、啟動多個子進(jìn)程(子進(jìn)程的執(zhí)行順序不是根據(jù)啟動順序決定的) import os from multiprocessing import Process def func(arg):print('子進(jìn)程%s :'%arg ,os.getpid(),os.getppid())if __name__ == '__main__':for i in range(10):Process(target=func,args=(i,)).start() 4、子進(jìn)程和父進(jìn)程之間的關(guān)系 1.父進(jìn)程和子進(jìn)程的啟動是異步的 父進(jìn)程只負(fù)責(zé)通知操作系統(tǒng)啟動子進(jìn)程 接下來的工作由操作系統(tǒng)接手 父進(jìn)程繼續(xù)執(zhí)行自己的代碼2.父進(jìn)程執(zhí)行完畢之后并不會直接結(jié)束程序, 而是會等待所有的子進(jìn)程都執(zhí)行完畢之后才結(jié)束 父進(jìn)程要負(fù)責(zé)回收子進(jìn)程的資源import time import os from multiprocessing import Process def func(arg):print('子進(jìn)程%s :'%arg ,os.getpid(),os.getppid())time.sleep(5)print('子進(jìn)程end')if __name__ == '__main__':for i in range(10):Process(target=func,args=(i,)).start()print('父進(jìn)程。。。')
?
5、join:父進(jìn)程等待子進(jìn)程結(jié)束后才繼續(xù)執(zhí)行自己后續(xù)的代碼 import time from multiprocessing import Process def func(name):print('Myname is:', name)time.sleep(1)print('我是子進(jìn)程')if __name__ == '__main__':p = Process(target=func, args=('xiaoming',))p.start()p.join()print('我是父進(jìn)程')結(jié)果: Myname is: xiaoming 我是子進(jìn)程 我是父進(jìn)程 ??
轉(zhuǎn)載于:https://www.cnblogs.com/yidashi110/p/10092171.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的进程初识和multiprocessing模块之Process的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 多线程六之Task(任务)三之任务
- 下一篇: mysql与Json学习总结