教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

通過fork()函數(shù)創(chuàng)建進程方法介紹

更新時間:2021年07月20日14時22分 來源:傳智教育 瀏覽次數(shù):

好口碑IT培訓(xùn)

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

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

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

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

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

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

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

---父進程---
---子進程---

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

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

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

圖2 進程的變化

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

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

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

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

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

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


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

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

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

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

我是父進程-2497, 子進程是2498
我是子進程-2498,父進程是2497



猜你喜歡:

寫爬蟲是用多進程好?還是多線程好?

什么是IP地址?使用IP地址和端口號能確定主機的進程嗎?

進程管理工具Supervisor安裝部署教程

傳智教育python+大數(shù)據(jù)開發(fā)高手班

0 分享到:
和我們在線交談!