日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux中的fork方法(python)

發布時間:2023/12/10 linux 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux中的fork方法(python) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

Unix/Linux操作系統提供了一個fork()系統調用,它非常特殊。普通的函數調用,調用一次,返回一次,但是fork()調用一次,返回兩次,因為操作系統自動把當前進程(稱為父進程)復制了一份(稱為子進程),然后,分別在父進程和子進程內返回。

子進程永遠返回0,而父進程返回子進程的ID。這樣做的理由是,一個父進程可以fork出很多子進程,所以,父進程要記下每個子進程的ID,而子進程只需要調用getppid()就可以拿到父進程的ID。

Python的os模塊封裝了常見的系統調用,其中就包括fork,可以在Python程序中輕松創建子進程。

一、fork入門知識

?????一個進程,包括代碼、數據和分配給進程的資源。fork()函數通過系統調用創建一個與原來進程幾乎完全相同的進程,

也就是兩個進程可以做完全相同的事,但如果初始參數或者傳入的變量不同,兩個進程也可以做不同的事。


??? 一個進程調用fork()函數后,系統先給新的進程分配資源,例如存儲數據和代碼的空間。然后把原來的進程的所有值都

復制到新的新進程中,只有少數值與原來的進程的值不同。相當于克隆了一個自己。

???? 我們來看一個例子:

import os print('Process (%s) start...' % os.getpid()) # Only works on Unix/Linux/Mac: count = 0 pid = os.fork() if pid == 0:print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))count += 1print("count:", count) else:print('I (%s) just created a child process (%s).' % (os.getpid(), pid))count += 1print("count:", count)

輸出:

Process (11844) start...
I (11844) just created a child process (11845).
count: 1
I am child process (11845) and my parent is 11844.
count: 1

?

在語句pid = os.fork()之前,只有一個進程在執行這段代碼,但在這條語句之后,就變成兩個進程在執行了,這兩個進程的幾乎完全相同,

將要執行的下一條語句都是print("pid:",pid)……
??? 為什么兩個進程的fpid不同呢,這與fork函數的特性有關。

fork調用的一個奇妙之處就是它僅僅被調用一次,卻能夠返回兩次,它可能有三種不同的返回值:
??? 1)在父進程中,fork返回新創建子進程的進程ID;
??? 2)在子進程中,fork返回0;

??? 在fork函數執行完畢后,如果創建新進程成功,則出現兩個進程,一個是子進程,一個是父進程。在子進程中,fork函數返回0,在父進程中,

fork返回新創建子進程的進程ID。我們可以通過fork返回的值來判斷當前進程是子進程還是父進程。

????引用一位網友的話來解釋fpid的值為什么在父子進程中不同:

? -? ? “其實就相當于鏈表,進程形成了鏈表,父進程的fpid(p 意味point)指向子進程的進程id,因為子進程沒有子進程,所以其fpid為0.

創建新進程成功后,系統中出現兩個基本完全相同的進程,這兩個進程執行沒有固定的先后順序,哪個進程先執行要看系統的進程調度策略。
??? 每個進程都有一個獨特(互不相同)的進程標識符(process ID),可以通過getpid()函數獲得,還有一個記錄父進程pid的變量,可以通過getppid()函數獲得變量的值。
fork執行完畢后,出現兩個進程,

有人說兩個進程的內容完全一樣啊,怎么打印的結果不一樣啊,那是因為判斷條件的原因,上面列舉的只是進程的代碼和指令,還有變量啊。


??? 執行完fork后,進程1的變量為count=0,fpid!=0(父進程)。進程2的變量為count=0,fpid=0(子進程),這兩個進程的變量都是獨立的,

存在不同的地址中,不是共用的,這點要注意??梢哉f,我們就是通過fpid來識別和操作父子進程的。


??? 還有人可能疑惑為什么不是從#include處開始復制代碼的,這是因為fork是把進程當前的情況拷貝一份,執行fork時,進程已經執行完了int count=0;

fork只拷貝下一個要執行的代碼到新的進程。

二、fork進階知識

????先看一份代碼:

import os print("i son/pa ppid pid fpid/n") #ppid指當前進程的父進程pid #pid指當前進程的pid, #fpid指fork返回給當前進程的值 for i in range(2):fpid = os.fork()if fpid == 0:print("%d child %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))else:print("%d parent %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))

輸出:

i son/pa ppid pid ?fpid/n
0 parent 12137 12333 12334
0 child ?12333 12334 ? ?0
1 parent 12137 12333 12335
1 parent 12333 12334 12336
1 child ?12333 12335 ? ?0
1 child ?12334 12336 ? ?0? ? ?

?

?? 這份代碼比較有意思,我們來認真分析一下:
????第一步:在父進程中,指令執行到for循環中,i=0,接著執行fork,fork執行完后,系統中出現兩個進程,分別是p12333和p12334

(后面我都用pxxxx表示進程id為xxxx的進程)。可以看到父進程p12333的父進程是p12334,子進程p12334的父進程正好是p12333。我們用一個鏈表來表示這個關系:
? ? p12137->p12333->p12334


第一次fork后,p12333(父進程)的變量為i=0,fpid=12334(fork函數在父進程中返向子進程id),代碼內容為:

for i in range(2):fpid = os.fork() # 執行完畢,i=0,fpid=12334if fpid == 0:print("%d child %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))else:print("%d parent %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))

?p12334(子進程)的變量為i=0,fpid=0(fork函數在子進程中返回0),代碼內容為:

for i in range(2):fpid = os.fork() # 執行完畢,i=0,fpid=0if fpid == 0:print("%d child %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))else:print("%d parent %4d %4d %4d" % (i, os.getppid(), os.getpid(), fpid))

所以打印出來的結果是:

0 parent 12137 12333 12334
0 child ?12333 12334 ? ?0

第二步:假設父進程p12333先執行,當進入下一個循環時,i=1,接著執行fork,系統中又新增一個進程p12335,對于此時的父進程,

p12137->p12333(當前進程)->p12335(被創建的子進程)。
??? 對于子進程p12334,執行完第一次循環后,i=1,接著執行fork,系統中新增一個進程p12336,對于此進程,

p12333->p12334(當前進程)->p12336(被創建的子進程)。

從輸出可以看到p12334原來是p12333的子進程,現在變成p12336的父進程。父子是相對的,這個大家應該容易理解。只要當前進程執行了fork,該進程就變成了父進程了,就打印出了parent。
? 所以打印出結果是:
???1 parent 12137 12333 12335
? ?1 parent 12333 12334 12336
????第三步:第二步創建了兩個進程p12335,p12336,這兩個進程執行完print函數后就結束了,因為這兩個進程無法進入第三次循環,無法fork,其他進程也是如此。
??? 以下是p12335,p123356打印出的結果:
????1 child ?12333 12335 ? ?0
? ? 1 child ?12334 12336 ? ?0? ? ?

??? 總結一下,這個程序執行的流程類似如下:

?這個程序最終產生了3個子進程,執行過6次print()函數。
??? 我們再來看一份代碼:

import os print("i son/pa ppid pid fpid/n") #ppid指當前進程的父進程pid #pid指當前進程的pid, #fpid指fork返回給當前進程的值 for i in range(3):fpid = os.fork()if fpid == 0:print("son")else:print("parent")

輸出:

?i son/pa ppid pid ?fpid/n
parent
son
parent
parent
parent
parent
son
parent
son
son
parent
son

?

?這里就不做詳細解釋了,只做一個大概的分析。

????for????????i=0???????? 1?????????? 2

??????????????father???? father???? father

????????????????????????????????????????son

????????????????????????????son?????? father

????????????????????????????????????????son

???????????????son?????? father???? father

????????????????????????????????????????son

????????????????????????????son?????? father

????????????????????????????????????????son

?

其中每一行分別代表一個進程的運行打印結果。

總結一下規律,對于這種N次循環的情況,執行printf函數的次數為2*(1+2+4+……+2N-1)次,創建的子進程數為1+2+4+……+2N-1個。

?

fork的內容就先到這里,

參考:

? ? ? ? (1)、https://www.cnblogs.com/jycboy/p/l_fork.html

? ? ? ? ?(2)、https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431927781401bb47ccf187b24c3b955157bb12c5882d000

總結

以上是生活随笔為你收集整理的linux中的fork方法(python)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。