文章目錄
- 多任務(wù)編程
- 進(jìn)程
- 進(jìn)程的優(yōu)先級(jí)
- 父子進(jìn)程
- 進(jìn)程相關(guān)的函數(shù)
- os.getpid()
- os.getppid()
- os._exit(status)
- sys.exit([status])
- 僵尸進(jìn)程
- 處理僵尸進(jìn)程的方法
- os.wait()
- os.waitpid(pid, option)
- 創(chuàng)建二級(jí)子進(jìn)程處理
- 在父進(jìn)程中使用信號(hào)處理的方法,忽略子進(jìn)程發(fā)來的信號(hào)
- 孤兒進(jìn)程
多任務(wù)編程
可以有效的利用計(jì)算機(jī)資源,同時(shí)執(zhí)行多個(gè)任務(wù)
進(jìn)程
進(jìn)程就是程序在計(jì)算機(jī)中一次執(zhí)行的過程
進(jìn)程和程序的區(qū)別:
程序是一個(gè)靜態(tài)文件的描述,不占計(jì)算機(jī)的系統(tǒng)資源
進(jìn)程是一個(gè)動(dòng)態(tài)的過程,占有CPU、內(nèi)存等資源,有一定的生命周期
同一個(gè)程序的不同執(zhí)行過程即為不同的進(jìn)程
問題1:什么決定了進(jìn)程的創(chuàng)建
1)用戶通過應(yīng)用層程序進(jìn)行進(jìn)程的創(chuàng)建申請(qǐng)
2)調(diào)用操作系統(tǒng)接口進(jìn)行進(jìn)程創(chuàng)建
3)告知系統(tǒng)內(nèi)核創(chuàng)建新的進(jìn)程提供給應(yīng)用層使用
問題2:進(jìn)程如何占有CPU
1)同一個(gè)內(nèi)核同一時(shí)刻只能運(yùn)行一個(gè)進(jìn)程
2)多個(gè)進(jìn)程對(duì)內(nèi)核資源進(jìn)行搶占,由操作系統(tǒng)內(nèi)核進(jìn)行分配
3)哪個(gè)進(jìn)程占有計(jì)算機(jī)內(nèi)核,我們稱為該進(jìn)程占有CPU的時(shí)間片
問題3:進(jìn)程在運(yùn)行過程中的形態(tài)和附帶內(nèi)容
1)PCB(進(jìn)程控制塊):在linux和unix操作系統(tǒng)中,進(jìn)程創(chuàng)建后會(huì)在內(nèi)存中開辟一塊空間存放進(jìn)程的相關(guān)信息,這個(gè)空間稱之為PCB
2)PID:在操作系統(tǒng)中進(jìn)程的唯一標(biāo)識(shí),是一個(gè)大于0的正整數(shù),由系統(tǒng)自動(dòng)分配
ps -aux 查看進(jìn)程信息
虛擬內(nèi)存:每個(gè)進(jìn)程占有4G內(nèi)存地址空間,這里的內(nèi)存指的是虛擬內(nèi)存
進(jìn)程狀態(tài):
三態(tài)
就緒態(tài): 進(jìn)程具備運(yùn)行條件,等待系統(tǒng)分配處理器以便運(yùn)行
運(yùn)行態(tài):進(jìn)程占有cpu處于運(yùn)行狀態(tài)
等待態(tài):又稱為阻塞態(tài)或者睡眠態(tài),指進(jìn)程不具備運(yùn)行條件,正在等待某些條件的達(dá)成
五態(tài)
就緒態(tài): 進(jìn)程具備運(yùn)行條件,等待系統(tǒng)分配處理器以便運(yùn)行
運(yùn)行態(tài):進(jìn)程占有cpu處于運(yùn)行狀態(tài)
等待態(tài):又稱為阻塞態(tài)或者睡眠態(tài),指進(jìn)程不具備運(yùn)行條件,正在等待某些條件的達(dá)成
新建:創(chuàng)建一個(gè)進(jìn)程的過程,直接表現(xiàn)為執(zhí)行某個(gè)程序或者在程序中創(chuàng)建新的進(jìn)程
終止:進(jìn)程執(zhí)行結(jié)束,完成回收的過程
D: 等待態(tài),不可中斷等待態(tài)
S: 等待態(tài),可中斷等待態(tài)
T: 等待態(tài),暫停狀態(tài)
R: 運(yùn)行態(tài)
Z: 僵尸態(tài)
+: 前臺(tái)進(jìn)程
N: 低優(yōu)先級(jí)的進(jìn)程
<: 高優(yōu)先級(jí)的進(jìn)程
l: 有進(jìn)程鏈接
s: 會(huì)話組
進(jìn)程的優(yōu)先級(jí)
優(yōu)先級(jí)往往決定了一個(gè)進(jìn)程的執(zhí)行權(quán)限和占有系統(tǒng)資源的優(yōu)先程度
top: 動(dòng)態(tài)查看系統(tǒng)進(jìn)程運(yùn)行情況
linux系統(tǒng)中優(yōu)先級(jí)范圍為-20—19,其中-20優(yōu)先級(jí)最高,19優(yōu)先級(jí)最低,0為平均狀態(tài),用戶創(chuàng)建進(jìn)程默認(rèn)優(yōu)先級(jí)為0
nice: 以指定的優(yōu)先級(jí)運(yùn)行某一個(gè)進(jìn)程
nice -9 ./while.py 以9的優(yōu)先級(jí)運(yùn)行程序
sudo nice --9 ./while.py 以-9的優(yōu)先級(jí)運(yùn)行程序
renice n PID: 修改一個(gè)正在運(yùn)行的進(jìn)程的優(yōu)先級(jí)
renice 8 4277 將4277號(hào)進(jìn)程優(yōu)先級(jí)修改為8
父子進(jìn)程
在系統(tǒng)中除了初始化進(jìn)程之外,每個(gè)進(jìn)程都是由父進(jìn)程創(chuàng)建的,每個(gè)進(jìn)程有一個(gè)唯一的父進(jìn)程,可能有多個(gè)子進(jìn)程
需求:兩間不相關(guān)事情希望同時(shí)來做
# test.py文件
import time
def fun1():
time.sleep(6)
print('做完第一件事情')
def fun2():
time.sleep(4)
print('做完第二件事情')
方案一:寫兩個(gè)進(jìn)程,分別承擔(dān)不同的事情,各自執(zhí)行
分析:1. 兩個(gè)程序比較麻煩
2. 無法確定兩個(gè)程序應(yīng)該在什么時(shí)間開始運(yùn)行
方案二:寫一個(gè)程序,在程序中指定位置調(diào)用接口來創(chuàng)建新的進(jìn)程
實(shí)現(xiàn)方法: os.fork()函數(shù)實(shí)現(xiàn)
fork()
功能:創(chuàng)建一個(gè)新的進(jìn)程
參數(shù):無
返回值:
小于0 表示進(jìn)程創(chuàng)建失敗
等于0 表示在子進(jìn)程中fork的返回值為0
大于0 在父進(jìn)程中fork的返回值大于0
-
fork是os模塊函數(shù),只能在linux和unix下使用
測試1:父進(jìn)程中fork之前的內(nèi)容,子進(jìn)程同樣也會(huì)復(fù)制,但是父子進(jìn)程空間內(nèi)容的修改不會(huì)相互影響
測試2:父子進(jìn)程在執(zhí)行上互不影響,理論上不一定誰先執(zhí)行
測試3:子進(jìn)程雖然復(fù)制父進(jìn)程的空間,但也有自己獨(dú)特的特性,比如自己的pid,進(jìn)程控制塊,進(jìn)程棧等。父進(jìn)程中fork的返回值即為創(chuàng)建的子進(jìn)程的pid號(hào)
# os模塊提供了大量和系統(tǒng)相關(guān)的功能函數(shù)接口
# os模塊的使用是系統(tǒng)相關(guān)的,在不同的系統(tǒng)中可能使用方法不同
import os
import time
# 創(chuàng)建新的進(jìn)程
pid = os.fork()
if pid < 0:
print('create process failed')
elif pid == 0:
print('pid:')
print(pid)
while True:
time.sleep(0.8)
print('This is the new process')
else:
# 父進(jìn)程中pid為子進(jìn)程的PID號(hào)
print('parent pid:')
print(pid)
while True:
time.sleep(1)
print('This is the parent process')
print('The process end')
需求解決:
import os
import time
# 導(dǎo)入test中的函數(shù)
from test import *
# 創(chuàng)建新的進(jìn)程
pid = os.fork()
if pid < 0:
print('create process failed')
elif pid == 0:
fun1()
else:
fun2()
進(jìn)程相關(guān)的函數(shù)
os.getpid()
功能:獲取當(dāng)前進(jìn)程的PID號(hào)
import os
pid = os.fork()
if pid < 0:
print('create process failed')
elif pid == 0:
print('Child process:')
print('當(dāng)前進(jìn)程的PID:', os.getpid())
else:
print('Parent process')
print('pid:', pid)
os.getppid()
功能:獲取當(dāng)前進(jìn)程父進(jìn)程的PID號(hào)
os._exit(status)
功能:用來結(jié)束一個(gè)進(jìn)程
參數(shù):一個(gè)數(shù)字,表示進(jìn)程的退出狀態(tài),通常0表示正常退出進(jìn)程,其他數(shù)字表示非正常退出
sys.exit([status])
功能:用來結(jié)束一個(gè)進(jìn)程, 如果處理了拋出的異常,則不結(jié)束進(jìn)程
參數(shù):一個(gè)數(shù)字,表示進(jìn)程的退出狀態(tài),同上
還可以是一個(gè)字符串,則在進(jìn)程退出時(shí)會(huì)打印這個(gè)字符串
import os
import sys
# 拋出異常進(jìn)程不結(jié)束
try:
sys.exit('over')
except SystemExit as e:
print(e)
print('process over')
僵尸進(jìn)程
子進(jìn)程先于父進(jìn)程退出,父進(jìn)程沒有對(duì)子進(jìn)程的退出做相應(yīng)的處理,此時(shí)子進(jìn)程就會(huì)變?yōu)榻┦M(jìn)程
影響:進(jìn)程退出后,仍有部分信息殘留在內(nèi)存中占用空間,大量的僵尸進(jìn)程會(huì)影響系統(tǒng)運(yùn)行,所以應(yīng)該盡量避免僵尸進(jìn)程的產(chǎn)生。
處理僵尸進(jìn)程的方法
- 讓父進(jìn)程先退出(不好控制)
- 父進(jìn)程處理子進(jìn)程的退出(阻塞父進(jìn)程的運(yùn)行)
os.wait()
功能:等待子進(jìn)程退出進(jìn)行處理
參數(shù):無
返回值:返回一個(gè)包含兩個(gè)元素的元組,第一個(gè)是退出的子進(jìn)程的PID號(hào),第二個(gè)是子進(jìn)程的退出狀態(tài)
- wait是一個(gè)阻塞函數(shù),即進(jìn)程處于等待狀態(tài),等待某種條件的達(dá)成才會(huì)繼續(xù)運(yùn)行
import os
import sys
from time import sleep
pid = os.fork()
if pid < 0:
print('create process failed')
elif pid == 0:
print('child process...')
sleep(2)
sys.exit(6) # 子進(jìn)程退出
else:
# wait 阻塞等待子進(jìn)程的退出
p, status = os.wait()
print('parent process...')
print('p, status:', p, status)
os.waitpid(pid, option)
功能:同wait, 處理子進(jìn)程退出,使其不會(huì)成為僵尸
參數(shù):
pid=-1表示等待任意子進(jìn)程退出
pid大于0表示等待指定進(jìn)程號(hào)的子進(jìn)程退出
option=0 表示阻塞等待
option=WNOHANG 表示非阻塞狀態(tài)
返回值:同wait
創(chuàng)建二級(jí)子進(jìn)程處理
# 創(chuàng)建二級(jí)子進(jìn)程解決僵尸進(jìn)程
import os
# 創(chuàng)建一級(jí)子進(jìn)程
pid = os.fork()
if pid < 0:
print('create process failed')
elif pid == 0:
# 創(chuàng)建二級(jí)子進(jìn)程
p = os.fork()
if p < 0:
print('process failed')
elif p == 0:
print('做二級(jí)子進(jìn)程任務(wù)')
else:
# 一級(jí)子進(jìn)程退出,使二級(jí)子進(jìn)程成為孤兒
os._exit(0)
else:
# 等待一級(jí)子進(jìn)程退出
os.wait()
print('做父進(jìn)程任務(wù)')
在父進(jìn)程中使用信號(hào)處理的方法,忽略子進(jìn)程發(fā)來的信號(hào)
signal(SIGCHLD, SIG_IGN)
孤兒進(jìn)程
父進(jìn)程先于子進(jìn)程退出,此時(shí)子進(jìn)程就會(huì)變?yōu)楣聝哼M(jìn)程
影響:當(dāng)一個(gè)進(jìn)程變?yōu)楣聝哼M(jìn)程,系統(tǒng)會(huì)自動(dòng)的使用一個(gè)進(jìn)程成為孤兒進(jìn)程的父進(jìn)程。當(dāng)孤兒進(jìn)程退出時(shí),該系統(tǒng)進(jìn)程會(huì)自動(dòng)回收孤兒,使他不會(huì)成為僵尸。所以孤兒進(jìn)程對(duì)系統(tǒng)資源沒有什么影響。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
