進(jìn)程的創(chuàng)建-fork
進(jìn)程VS程序
編寫完畢的代碼,在沒有運行的時候,稱之為程序
正在運行著的代碼霉赡,就成為進(jìn)程
進(jìn)程,除了包含代碼以外幔托,還有需要運行的環(huán)境等穴亏,所以和程序是有區(qū)別的
fork()
Python的os模塊封裝了常見的系統(tǒng)調(diào)用,其中就包括fork重挑,可以在Python程序中輕松創(chuàng)建子進(jìn)程:
說明:
·程序執(zhí)行到os.fork()時嗓化,操作系統(tǒng)會創(chuàng)建一個新的進(jìn)程(子進(jìn)程),然后復(fù)制父進(jìn)程的所有信息到子進(jìn)程中
·然后父進(jìn)程和子進(jìn)程都會從fork()函數(shù)中得到一個返回值谬哀,在子進(jìn)程中這個值一定是0刺覆,而父進(jìn)程中是子進(jìn)程的id號
在Unix/Linux操作系統(tǒng)中,提供了一個fork()系統(tǒng)函數(shù)史煎,它非常特殊谦屑。
普通的函數(shù)調(diào)用,調(diào)用一次篇梭,返回一次氢橙,但是fork()調(diào)用一次,返回兩次恬偷,因為操作系統(tǒng)自動把當(dāng)前進(jìn)程(稱為父進(jìn)程)復(fù)制了一份(稱為子進(jìn)程)悍手,然后,分別在父進(jìn)程和子進(jìn)程內(nèi)返回袍患。
子進(jìn)程永遠(yuǎn)返回0坦康,而父進(jìn)程返回子進(jìn)程的ID。
這樣做的理由是协怒,一個父進(jìn)程可以fork出很多子進(jìn)程涝焙,所以,父進(jìn)程要記下每個子進(jìn)程的ID孕暇,而子進(jìn)程只需要調(diào)用getppid()就可以拿到父進(jìn)程的ID仑撞。
getpid()、getppid()
多進(jìn)程修改全局變量
總結(jié):
·多進(jìn)程中妖滔,每個進(jìn)程中所有數(shù)據(jù)(包括全局變量)都各有擁有一份隧哮,互不影響
多次fork問題
multiprocessing
如果你打算編寫多進(jìn)程的服務(wù)程序,Unix/Linux無疑是正確的選擇座舍。由于Windows沒有fork調(diào)用沮翔,難道在Windows上無法用Python編寫多進(jìn)程的程序?
由于Python是跨平臺的曲秉,自然也應(yīng)該提供一個跨平臺的多進(jìn)程支持采蚀。multiprocessing模塊就是跨平臺版本的多進(jìn)程模塊疲牵。
multiprocessing模塊提供了一個Process類來代表一個進(jìn)程對象,下面的例子演示了啟動一個子進(jìn)程并等待其結(jié)束:
說明
·創(chuàng)建子進(jìn)程時榆鼠,只需要傳入一個執(zhí)行函數(shù)和函數(shù)的參數(shù)纲爸,創(chuàng)建一個Process實例,用start()方法啟動妆够,這樣創(chuàng)建進(jìn)程比fork()還要簡單识啦。
·join()方法可以等待子進(jìn)程結(jié)束后再繼續(xù)往下運行,通常用于進(jìn)程間的同步神妹。
Process語法結(jié)構(gòu)如下:
Process([group [, target [, name [, args [,kwargs]]]]])
·target:表示這個進(jìn)程實例所調(diào)用對象颓哮;
·args:表示調(diào)用對象的位置參數(shù)元組;
·kwargs:表示調(diào)用對象的關(guān)鍵字參數(shù)字典鸵荠;
·name:為當(dāng)前進(jìn)程實例的別名冕茅;
·group:大多數(shù)情況下用不到;
Process類常用方法:
·is_alive():判斷進(jìn)程實例是否還在執(zhí)行腰鬼;
·join([timeout]):是否等待進(jìn)程實例執(zhí)行結(jié)束嵌赠,或等待多少秒;
·start():啟動進(jìn)程實例(創(chuàng)建子進(jìn)程)熄赡;
·run():如果沒有給定target參數(shù)姜挺,對這個對象調(diào)用start()方法時,就將執(zhí)行對象中的run()方法彼硫;
·terminate():不管任務(wù)是否完成炊豪,立即終止;
Process類常用屬性:
·name:當(dāng)前進(jìn)程實例別名拧篮,默認(rèn)為Process-N词渤,N為從1開始遞增的整數(shù);
·pid:當(dāng)前進(jìn)程實例的PID值串绩;