進程初識和multiprocessing模塊之Process

複製代碼
1、什麼是進程
進程就是運行中的程序

進程是操做系統中最小的資源分配單位

進程與進程之間的關係 : 數據隔離的

進程的id:Process id = pid pid是一個全系統惟一的對某個進程的標識,隨着這個進程的重啓pid可能會變化

程序與進程的區別
程序是指令和數據的有序集合,其自己沒有任何運行的含義,是一個靜態的概念。 而進程是程序在處理機上的一次執行過程,它是一個動態的概念。 程序能夠做爲一種軟件資料長期存在,而進程是有必定生命期的。 程序是永久的,進程是暫時的。
進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操做系統結構的基礎。在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體。

狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being executed)。
廣義定義:進程是一個具備必定獨立功能的程序關於某個數據集合的一次運行活動。它是操做系統動態執行的基本單元,在傳統的操做系統中,進程既是基本的分配單元,也是基本的執行單元。
進程
第一,進程是一個實體。每個進程都有它本身的地址空間,通常狀況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。
第二,進程是一個「執行中的程序」。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操做系統執行之),它才能成爲一個活動的實體,咱們稱其爲進程。[3] 
進程是操做系統中最基本、重要的概念。是多道程序系統出現後,爲了刻畫系統內部出現的動態狀況,描述系統內部各道程序的活動規律引進的一個概念,全部多道程序設計操做系統都創建在進程的基礎上。
概念
動態性:進程的實質是程序在多道程序系統中的一次執行過程,進程是動態產生,動態消亡的。
併發性:任何進程均可以同其餘進程一塊兒併發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
異步性:因爲進程間的相互制約,使進程具備執行的間斷性,即進程按各自獨立的、不可預知的速度向前推動
結構特徵:進程由程序、數據和進程控制塊三部分組成。
多個不一樣的進程能夠包含相同的程序:一個程序在不一樣的數據集裏就構成不一樣的進程,能獲得不一樣的結果;可是執行過程當中,程序不能發生改變。
特徵
 
  

2、進程的調度
要想多個進程交替運行,操做系統必須對這些進程進行調度,這個調度也不是隨即進行的,而是須要遵循必定的法則,由此就有了進程的調度算法。

一、先來先服務
先來先服務(FCFS)調度算法是一種最簡單的調度算法,該算法既可用於做業調度,也可用於進程調度。FCFS算法比較有利於長做業(進程),而不利於短做業(進程)。
由此可知,本算法適合於CPU繁忙型做業,而不利於I/O繁忙型的做業(進程)。
二、短做業優先
短做業(進程)優先調度算法(SJ/PF)是指對短做業或短進程優先調度的算法,該算法既可用於做業調度,也可用於進程調度。但其對長做業不利;不能保證緊迫性做業(進程)被及時處理;
做業的長短只是被估算出來的。

三、時間片輪轉法
時間片輪轉(Round Robin,RR)法的基本思路是讓每一個進程在就緒隊列中的等待時間與享受服務的時間成比例。在時間片輪轉法中,須要將CPU的處理時間分紅固定大小的時間片,
例如,幾十毫秒至幾百毫秒。若是一個進程在被調度選中以後用完了系統規定的時間片,但又未完成要求的任務,則它自行釋放本身所佔有的CPU而排到就緒隊列的末尾,等待下一次調度。
同時,進程調度程序又去調度當前就緒隊列中的第一個進程。
四、多級反饋隊列
前面介紹的各類用做進程調度的算法都有必定的侷限性。如短進程優先的調度算法,僅照顧了短進程而忽略了長進程,並且若是並未指明進程的長度,則短進程優先和基於進程長度的搶佔式調度算法都將沒法使用。而多級反饋隊列調度算法則沒必要事先知道各類進程所需的執行時間,並且還能夠知足各類類型進程的須要,於是它是目前被公認的一種較好的進程調度算法。在採用多級反饋隊列調度算法的系統中,調度算法的實施過程以下所述。
(1) 應設置多個就緒隊列,併爲各個隊列賦予不一樣的優先級。第一個隊列的優先級最高,第二個隊列次之,其他各隊列的優先權逐個下降。該算法賦予各個隊列中進程執行時間片的大小也各不相同,在優先權愈高的隊列中,爲每一個進程所規定的執行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。
(2) 當一個新進程進入內存後,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度。當輪到該進程執行時,如它能在該時間片內完成,即可準備撤離系統;若是它在一個時間片結束時還沒有完成,調度程序便將該進程轉入第二隊列的末尾,再一樣地按FCFS原則等待調度執行;若是它在第二隊列中運行一個時間片後仍未完成,再依次將它放入第三隊列,……,如此下去,當一個長做業(進程)從第一隊列依次降到第n隊列後,在第n 隊列便採起按時間片輪轉的方式運行。
(3) 僅當第一隊列空閒時,調度程序才調度第二隊列中的進程運行;僅當第1~(i-1)隊列均空時,纔會調度第i隊列中的進程運行。若是處理機正在第i隊列中爲某進程服務時,又有新進程進入優先權較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進程將搶佔正在運行進程的處理機,即由調度程序把正在運行的進程放回到第i隊列的末尾,把處理機分配給新到的高優先權進程。






3、進程的並行與併發
並行 : 並行是指二者同時執行,好比賽跑,兩我的都在不停的往前跑;(資源夠用,好比三個線程,四核的CPU )
併發 : 併發是指資源有限的狀況下,在一個時間段內二者交替輪流使用資源,好比一個單核CPU資源一次只能給一個進程使用,A使用一段時間後,讓給B,B用完繼續給A ,交替使用,目的是提升效率。

區別:
並行是從微觀上,也就是在一個精確的時間片刻,有不一樣的程序在執行,這就要求必須有多個處理器。
併發是從宏觀上,在一個時間段上能夠看出是同時執行的,好比一個服務器同時處理多個session。



4、同步異步阻塞非阻塞
一、三狀態介紹:



在程序運行的過程當中,因爲被操做系統的調度算法控制,程序會進入幾個狀態:就緒,運行和阻塞。
一、就緒(Ready)狀態
當進程已分配到除CPU之外的全部必要的資源,只要得到CPU即可當即執行,這時的進程狀態稱爲就緒狀態。

二、執行/運行(Running)狀態
當進程已得到處理器,其程序正在處理器上執行,此時的進程狀態稱爲執行狀態。

三、阻塞(Blocked)狀態
正在執行的進程,因爲等待某個事件發生而沒法執行時,便放棄處理器而進入阻塞狀態。引發進程阻塞的事件可有多種,例如,等待I/O完成、申請緩衝區不能知足、等待信件(信號)等。





二、同步異步
同步:兩件事 一件作完了再去作另外一件事兒
例如:我先去洗衣服(手洗),洗完衣服再去作飯

異步:兩件事情同時作
例如:我有洗衣機了,我能夠打開洗衣機,在洗衣機洗衣服的時候,我去作飯

三、阻塞和非阻塞
阻塞:例如socket編程中,服務端使用accept,就是阻塞,它會在那裏一直等待客戶端來鏈接它
好比:你在洗衣服的時候沒有洗衣粉,等待洗衣粉而中止。

非阻塞:例如socket編程中,服務端對象使用setblocking(True),在accept的時候不會進行等待,而是繼續向下運行
好比:有洗衣粉了,能夠直接洗衣粉

同步阻塞 :不能充分利用CPU(效率最低)
好比:你在洗衣服的時候,沒有洗衣粉了,等待洗衣粉而中止,有洗衣粉後,洗完衣服了,而後去作飯,又沒有米了,等待米而中止

異步非阻塞 : 過分利用CPU(效率很高)
好比:你在洗衣服的時候,沒有洗衣粉了,可是你不中止,而是直接開洗衣機洗衣服,同時在作飯的時候,又沒有米了,你也直接煮




5、進程的建立與結束
建立
而對於通用系統(跑不少應用程序),須要有系統運行過程當中建立或撤銷進程的能力,主要分爲4中形式建立新的進程:
1. 系統初始化

2. 一個進程在運行過程當中開啓了子進程

3. 用戶的交互式請求,而建立一個新進程(如用戶QQ)

4. 一個批處理做業的初始化(只在大型機的批處理系統中應用)

不管哪種,新進程的建立都是由一個已經存在的進程執行了一個用於建立進程的系統調用而建立的。 

結束
1. 正常退出(自願,如用戶點擊交互式頁面的叉號,或程序執行完畢調用發起系統調用正常退出,在linux中用exit,在windows中用ExitProcess)

2. 出錯退出(自願,python a.py中a.py不存在)

3. 嚴重錯誤(非自願,執行非法指令,如引用不存在的內存,1/0等,能夠捕捉異常,try...except...)

4. 被其餘進程殺死(非自願)




6、multiprocessing模塊
一、模塊介紹
Process模塊是一個建立進程的模塊,藉助這個模塊,就能夠完成進程的建立。
Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化獲得的對象,表示一個子進程中的任務(還沒有啓動)

強調:
1. 須要使用關鍵字的方式來指定參數
2. args指定的爲傳給target函數的位置參數,是一個元組形式,必須有逗號

參數介紹:
1 group參數未使用,值始終爲None
2 target表示調用對象,即子進程要執行的任務
3 args表示調用對象的位置參數元組,args=(1,2,'a',)
4 kwargs表示調用對象的字典,kwargs={'name':'ming','age':18}
5 name爲子進程的名稱
 
方法介紹
一、 p.start():啓動進程,並調用該子進程中的p.run() 二、 p.run():進程啓動時運行的方法,正是它去調用target指定的函數,咱們自定義類的類中必定要實現該方法 三、 p.terminate():強制終止進程p,不會進行任何清理操做,若是p建立了子進程,該子進程就成了殭屍進程,使用該方法須要特別當心這種狀況。若是p還保存了一個鎖那麼也將不會被釋放,進而致使死鎖 四、 p.is_alive():若是p仍然運行,返回True 五、 p.join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,而p是處於運行的狀態)。timeout是可選的超時時間,須要強調的是,p.join只能join住start開啓的進程,而不能join住run開啓的進程



屬性介紹
一、 p.daemon:默認值爲False,若是設爲True,表明p爲後臺運行的守護進程,當p的父進程終止時,p也隨之終止,而且設定爲True後,p不能建立本身的新進程,必須在p.start()以前設置
二、 p.name:進程的名稱
三、 p.pid:進程的pid
四、 p.exitcode:進程在運行時爲None、若是爲–N,表示被信號N結束(瞭解便可) 五、 p.authkey:進程的身份驗證鍵,默認是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是爲涉及網絡鏈接的底層進程間通訊提供安全性,這類鏈接只有在具備相同的身份驗證鍵時才能成功(瞭解便可)


在windows中使用須要注意
在Windows操做系統中因爲沒有fork(linux操做系統中建立進程的機制),在建立子進程的時候會自動 import 啓動它的這個文件,而在 import 的時候又執行了整個文件。所以若是將process()直接寫在文件中就會無限遞歸建立子進程報錯。
因此必須把建立子進程的部分使用if __name__ =='__main__' 判斷保護起來,import 的時候 ,就不會遞歸運行了。
 
  



例子:
複製代碼
1import os
import time
from multiprocessing import Process
def func(arg):
    time.sleep(0.5)
    print('子進程%s,子進程id:%s,父進程id:%s'%(arg,os.getpid(),os.getppid())) # os.getpid當前進程id,os.getppid父進程id  注意與屬性p.pid的區分

if __name__ == '__main__':
    p = Process(target=func,args=(1,))  # 實例化一個進程,Process是一個類
    p.start()
    print('主進程id:%s,主進程的父進程id:%s,子進程id:%s' % (os.getpid(), os.getppid(), p.pid))
複製代碼
 
  
複製代碼
2、數據隔離
import os
from multiprocessing import Process
count = 100
def func():
    global count
    count -= 1
    print('子進程:',count)

if __name__ == '__main__':
    print('主進程',os.getpid(),os.getppid())
    p = Process(target=func)
    p.start()
    print('主進程:',count)

結果:
主進程 8316 5512
主進程: 100
子進程: 99
複製代碼


複製代碼
3、啓動多個子進程(子進程的執行順序不是根據啓動順序決定的)
import os
from multiprocessing import Process
def func(arg):
    print('子進程%s :'%arg ,os.getpid(),os.getppid())

if __name__ == '__main__':
    for i in range(10):
        Process(target=func,args=(i,)).start()
複製代碼
 
  
複製代碼
4、子進程和父進程之間的關係
1.父進程和子進程的啓動是異步的
父進程只負責通知操做系統啓動子進程
接下來的工做由操做系統接手 父進程繼續執行本身的代碼

2.父進程執行完畢以後並不會直接結束程序,
而是會等待全部的子進程都執行完畢以後才結束
父進程要負責回收子進程的資源

import time
import os
from multiprocessing import Process
def func(arg):
    print('子進程%s :'%arg ,os.getpid(),os.getppid())
    time.sleep(5)
    print('子進程end')

if __name__ == '__main__':
    for i in range(10):
        Process(target=func,args=(i,)).start()
    print('父進程。。。')
複製代碼

 

複製代碼
5、join:父進程等待子進程結束後才繼續執行本身後續的代碼
import time
from multiprocessing import Process
def func(name):
    print('Myname is:', name)
    time.sleep(1)
    print('我是子進程')


if __name__ == '__main__':
    p = Process(target=func, args=('xiaoming',))
    p.start()
    p.join()
    print('我是父進程')

結果:
Myname is: xiaoming
我是子進程
我是父進程
複製代碼
 
複製代碼
相關文章
相關標籤/搜索