首頁技術(shù)文章正文

fork()函數(shù)創(chuàng)建進(jìn)程操作演示

更新時間:2021-07-20 來源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

在Unix/Linux操作系統(tǒng)中,通過Python的os模塊中封裝的fork()函數(shù)可以輕松地創(chuàng)建一個進(jìn)程。fork()函數(shù)的聲明如下:

fork()
以上函數(shù)調(diào)用后,操作系統(tǒng)會建立當(dāng)前線程的副本以實現(xiàn)進(jìn)程的創(chuàng)建,此時原有的進(jìn)程被稱為父進(jìn)程,復(fù)制的進(jìn)程被稱為子進(jìn)程。需要注意的是,fork()函數(shù)的一次調(diào)用產(chǎn)生兩個結(jié)果:若當(dāng)前執(zhí)行是父進(jìn)程,fork()函數(shù)返回子進(jìn)程ID;若當(dāng)前執(zhí)行的進(jìn)程是子進(jìn)程,fork()函數(shù)返回0。如果fork()函數(shù)調(diào)用時出現(xiàn)錯誤,進(jìn)程創(chuàng)建失敗,將返回一個負(fù)值。

下面使用fork()函數(shù)創(chuàng)建一個子進(jìn)程,讓父進(jìn)程和子進(jìn)程分別執(zhí)行不同的任務(wù),代碼如下:

import os
import time
value = os.fork()             # 創(chuàng)建子進(jìn)程
if value == 0:                 # 子進(jìn)程執(zhí)行if分支語句
  print('---子進(jìn)程---')
  time.sleep(2)
else:                       # 父進(jìn)程執(zhí)行else分支語句
  print('---父進(jìn)程---')
  time.sleep(2)

以上程序調(diào)用fork()函數(shù)創(chuàng)建子進(jìn)程,使用變量value記錄fork()的返回值,并根據(jù)fork()的返回結(jié)果區(qū)分父進(jìn)程與子進(jìn)程,為這兩個進(jìn)程分派不同的任務(wù):當(dāng)value為0時,說明當(dāng)前進(jìn)程是子進(jìn)程,執(zhí)行if分支中的語句;當(dāng)value不為0時,說明此時系統(tǒng)調(diào)度的是父進(jìn)程,執(zhí)行else分支中的語句。進(jìn)程創(chuàng)建與程序執(zhí)行的具體流程如圖1所示。

fork()函數(shù)創(chuàng)建進(jìn)程

圖1 使用fork()函數(shù)創(chuàng)建進(jìn)程

程序執(zhí)行一次的結(jié)果如下所示:

---父進(jìn)程---
---子進(jìn)程---

觀察此次結(jié)果可以推測,系統(tǒng)先調(diào)度父進(jìn)程,再調(diào)度子進(jìn)程,但實際上,子進(jìn)程和父進(jìn)程執(zhí)行的順序是不確定的,會受到時間片、調(diào)度優(yōu)先級或其它因素的影響。

若程序中順序調(diào)用兩次fork()函數(shù),那么第一次調(diào)用fork()后系統(tǒng)中存在的兩個進(jìn)程都會調(diào)用第二個fork()函數(shù)創(chuàng)建新進(jìn)程,兩次fork()函數(shù)后進(jìn)程的變化如圖2所示。

fork()函數(shù)創(chuàng)建進(jìn)程

圖2 進(jìn)程的變化

從圖2中可以看出,“父進(jìn)程1”和“子進(jìn)程1”再次復(fù)制出兩個子進(jìn)程,“父進(jìn)程1”成為“子進(jìn)程2”的父進(jìn)程,“子進(jìn)程1”成為“子進(jìn)程3”的父進(jìn)程,變成“父進(jìn)程2”。

下面使用fork()函數(shù)創(chuàng)建3個子進(jìn)程,代碼如下:

import os
import time
print('---第一次fork()調(diào)用---')
value = os.fork()      # 創(chuàng)建子進(jìn)程,此時進(jìn)程的總數(shù)量為2
if value == 0:          # 子進(jìn)程執(zhí)行if分支語句
    print('---進(jìn)程1---')
    time.sleep(2)
else:                     # 父進(jìn)程執(zhí)行else分支語句
    print('---進(jìn)程2---')
    time.sleep(2)
print('---第二次fork()調(diào)用---')
value = os.fork()       # 創(chuàng)建子進(jìn)程,此時進(jìn)程的總數(shù)量為4
if value == 0:           # 子進(jìn)程執(zhí)行if分支語句
    print('---進(jìn)程3---')
    time.sleep(2)
else:                      # 父進(jìn)程執(zhí)行else分支語句
    print('---進(jìn)程4---')
    time.sleep(2)

程序執(zhí)行的結(jié)果如下:

---第一次fork()調(diào)用---
---進(jìn)程2---
---進(jìn)程1---
---第二次fork()調(diào)用---
---進(jìn)程4---
---進(jìn)程4---
---進(jìn)程3---
---進(jìn)程3---

由執(zhí)行結(jié)果可知,程序在第一次調(diào)用fork()函數(shù)后創(chuàng)建了一個子進(jìn)程,此時共有父進(jìn)程和子進(jìn)程執(zhí)行下面的代碼,分別輸出 “---進(jìn)程2---”和“---進(jìn)程1---”;程序在第二次調(diào)用fork()函數(shù)后又創(chuàng)建了兩個新的子進(jìn)程,此時共有兩個父進(jìn)程和兩個子進(jìn)程執(zhí)行下面的代碼,分別輸出兩次“---進(jìn)程4---”和“---進(jìn)程3---”。


獲取當(dāng)前進(jìn)程的ID

進(jìn)程ID是進(jìn)程的唯一標(biāo)識,為了便于管理系統(tǒng)中的進(jìn)程,os模塊提供了os.getpid()函數(shù)和os.getppid()函數(shù)來分別獲取當(dāng)前進(jìn)程id和當(dāng)前進(jìn)程父進(jìn)程的id,示例代碼如下:

import os
process = os.fork() # 創(chuàng)建子進(jìn)程
if process == 0: 
    # 獲取父進(jìn)程的ID 
    print('我是子進(jìn)程-%d,父進(jìn)程是%d'%(os.getpid(), os.getppid()))  
else:
    print('我是父進(jìn)程-%d, 子進(jìn)程是%d'%(os.getpid(), process)) # 獲取當(dāng)前線程的ID

程序運行的結(jié)果如下:

我是父進(jìn)程-2497, 子進(jìn)程是2498
我是子進(jìn)程-2498,父進(jìn)程是2497






猜你喜歡:

什么是Python的進(jìn)程?進(jìn)程組成部分內(nèi)容介紹

孤兒進(jìn)程和僵尸進(jìn)程概念|如何避免僵尸進(jìn)程?

IP地址是什么意思?怎樣能確定一臺主機(jī)的進(jìn)程?

黑馬程序員python+大數(shù)據(jù)開發(fā)培訓(xùn)

分享到:
在線咨詢 我要報名
和我們在線交談!