天天看點

(五)程序相關函數,孤兒程序,僵屍程序

程序相關函數使用

os.getpid()

功能:擷取目前程序的PID号

傳回值:傳回PID号

os.getppid()

功能:擷取父程序的程序号

傳回值:傳回PID号

os._exit(status)

功能:退出程序

參數:程序的退出狀态 整數

import os 

pid = os.fork()

if pid < 0:
    print("Create Process failed")
elif pid == 0:
    print("子程序PID",os.getpid())
    print("Parent PID",os.getppid())
else:
    print("父程序PID",os.getpid())
    print("Child PID",pid)
           
import os 
import sys 
#程序結束
# os._exit(0)
try:
    sys.exit("程序退出")
except SystemExit as e:
    print(e)
print("Process end")
#建立二級子程序
import os 
from time import sleep 
def fun1():
    sleep(3)
    print("第一件事情")
def fun2():
    sleep(4)
    print("第二件事情")
pid = os.fork()
if pid < 0:
    print("Create process error")
elif pid == 0:
    #建立二級程序
    pid0 = os.fork()
    if pid0 < 0:
        print("建立二級程序失敗")
    elif pid0 == 0:
        fun2()  #做第二件事
    else:
        os._exit(0)
else:
    os.wait()
    fun1() #做第一件事
           

sys.exit([status])

功能: 退出程序

參數: 不寫預設為0

    傳入一個整數表示退出狀态

    傳入一個字元串,則在程序退出時會列印該字元串

* sys.exit 可以通過捕獲 SystemExit 異常阻止其退出

import os,sys 
from time import sleep 
pid = os.fork()
if pid < 0:
    print("create process failed")
elif pid == 0:
    print("父程序pid:",os.getppid())
    sleep(2)
    print("父程序PID:",os.getppid())
else: 
    sleep(1)
    print("Parent PID:",os.getpid())
    sys.exit("父程序退出")
           
​​​​​​​import os,sys 
from time import sleep
pid = os.fork()
​​​​​​​if pid < 0:
    print("create process failed")
elif pid == 0:
    print("子程序PID:",os.getpid())
    sys.exit("子程序退出")
else: 
    sleep(1)
    while True:
        pass    
def fun(a):
    a = "Nihao China"
s = "hello world"
fun(s)
print(s)
           

孤兒程序:父程序先于子程序退出,此時子程序就會成為孤兒程序。

* 孤兒程序會被系統指定的程序收養,即系統程序會成為該孤兒程序新的父程序,孤兒程序退出時該父程序會處理退出狀态

僵屍程序:子程序先于父程序退出,父程序沒有處理子程序退出狀态,此時子程序成為僵屍程序

* 僵屍程序已經結束,但是會滞留部分PCB資訊在記憶體,大量的僵屍會消耗系統資源,應該盡量避免

如何避免僵屍程序産生

* 父程序先退出

* 父程序處理子程序退出狀态

pid,status = os.wait()

功能:在父程序中阻塞等待處理子程序的退出

傳回值:pid 退出的子程序的PID号

       status  子程序的退出狀态

pid,status = os.waitpid(pid,option)

功能:同wait

參數:pid  -1  表示任意子程序退出

           >0  整數  指定PID号的子程序退出

    option  0  表示阻塞等待

           WNOHANG 表示非阻塞

傳回值:同wait

waitpid(-1,0)  ====  wait()

 

* 父程序先退出

建立二級子程序

    1.父程序建立子程序等待子程序退出

    2.子程序建立二級子程序,然後馬上退出

    3.二級子程序成為孤兒,處理具體事件

multiprocessing 子產品建立程序

1.需要将要做的事件封裝為函數

2.使用multiprocessing中提供的process類建立程序

3.通過程序對象和process 初始化函數對程序進行設定,并且綁定要執行的事件

4.啟動程序,會自動執行相關聯函數

5.事件完成後回收程序

建立程序對象

process()

功能:建立程序對象

參數:name : 給建立的程序對象起一個名字

            預設process-1

    target : 綁定的函數

    args : 元組 給target函數按照位置傳參

    kwargs : 字典 給target函數按照鍵值出傳參

p.start()

功能: 啟動程序,此時程序被建立。自動運作程序函數

p.join([timeout])

功能:阻塞等待回收響應的程序

參數:逾時時間

* multiprocessing建立程序是原來程序的子程序,建立後父子程序各自執行互不影響

* 子程序同樣是複制父程序的空間,子程序對内容的修改不會影響父程序空間

* join回收子程序,會有效的阻止僵屍程序産生

import multiprocessing as mp 
from time import sleep 
import os 
a = 1
#程序事件
def fun():
    # print("a = ",a)
    global a 
    a = 10000
    print(os.getpid())
    sleep(3)
    print("子程序事件")
p = mp.Process(target = fun)#建立程序對象
p.start()#啟動程序
sleep(2)
print("這是父程序")
p.join()​​​​​​​#回收程序
while True:
    pass
print("===================")
# print(a)
           
import os,sys 
from time import sleep
pid = os.fork()
​​​​​​​if pid < 0:
    print("create process failed")
elif pid == 0:
    sleep(3)
    print("子程序PID:",os.getpid())
    sys.exit(3)
else: 
    #等待子程序退出
    pid,status = os.wait()
    print(pid,status)
    print(os.WEXITSTATUS(status)) #擷取退出狀态
    while True:
        pass  
           
import os,sys 
from time import sleep
pid = os.fork()
​​​​​​​if pid < 0:
    print("create process failed")
elif pid == 0:
    sleep(3)
    print("子程序PID:",os.getpid())
    sys.exit(3)
else: 
    #等待子程序退出
    while True:
        sleep(1)
        pid,status = os.waitpid(-1,os.WNOHANG)
        print(pid,status)
        if os.WEXITSTATUS(status):
            break
        print("do something others")
    while True:
        pass  
           

作業: multipeocessing  對照fork

      建立父子程序,複制一個檔案,父子程序各複制一半到一個新的檔案中

import os 
from multiprocessing import Process
from time import sleep

size = os.path.getsize("./img.jpg")
# 如果在父程序打開則兩個子程序操作同一個檔案流
# fr = open('img.jpg','rb')

#複制上半部分
def copy1(filename):
    fr = open(filename,'rb')
    n = size // 2 
    fw = open('copy1.jpg','wb')

    while True:
        if n < 1024:
            data = fr.read(n)
            fw.write(data)
            break
        data = fr.read(1024)
        fw.write(data)
        n -= 1024
    fr.close()
    fw.close()

#複制下半部分
def copy2(filename):
    fr = open(filename,'rb')
    fw = open('copy2.jpg','wb')
    fr.seek(size // 2,0)  #檔案偏移位置到中間

    while True:
        data = fr.read(1024)
        if not data:
            break 
        fw.write(data)
    fw.close()
    fr.close()

p1 = Process(target = copy1,args = ("img.jpg",))
p2 = Process(target = copy2,args = ("img.jpg",))

p2.start()
sleep(0.5)
p1.start()

p1.join()
p2.join()
           

繼續閱讀