什么是 fork() 系统调用以及如何使用 Python 进行 fork
在进入 fork 之前,让我们了解一下什么是过程。计算机术语中的进程是计算机当前正在执行的程序。每个进程都是唯一的,可以通过其 PID 或进程 ID 来标识。 注意:下面显示的所有示例和演示代码均在 Ubuntu 20.04 LTS 和 Python v3.8.5 上进行了尝试。 访问我的 Github 页面以获取所有演示代码片段https://github.com/jaqsparow/fork-
在进入 fork 之前,让我们了解一下什么是过程。计算机术语中的进程是计算机当前正在执行的程序。每个进程都是唯一的,可以通过其 PID 或进程 ID 来标识。
- 注意:下面显示的所有示例和演示代码均在 Ubuntu 20.04 LTS 和 Python v3.8.5 上进行了尝试。
访问我的 Github 页面以获取所有演示代码片段https://github.com/jaqsparow/fork-demos
我们将在这篇文章中学到什么?
-
什么是分叉💡
-
如何在 python 中调用 fork 📗
-
如何在 Python 中获取进程 ID 或 PID 📙
-
如何识别父子进程📕
-
个带有代码片段的示例💻
简介:什么是fork系统调用?
Fork 是 Unix 和 Linux 操作系统中最重要的概念之一。简而言之,fork 只不过是克隆一个进程。这意味着 fork 将创建一个具有调用进程的精确副本的新进程。因此,当程序遇到 fork() 系统调用时,它将创建另一个具有相同内存副本的进程。所以这里出现了父子进程的概念。
调用fork并创建新进程的主进程或第一个进程称为父进程。 fork 创建的新进程称为子进程。
如何识别父子进程?
由于子进程和父进程都有完全相同的内存副本,那么问题来了,我们如何识别它们中的哪一个是父进程,哪一个是子进程。正如我上面提到的,每个进程都有唯一的 ID,称为进程 ID 或 PID,可用于区分进程。
为了识别父子进程,我们需要检查fork系统调用的返回码。
fork()的返回码
fork 系统调用的返回码决定了父进程还是子进程。当父进程调用fork时,fork将刚刚创建的子进程的PID返回给父进程,返回0给子进程。所以基本上如果来自 fork 调用的返回码为零,那么它的子进程,如果它是一个正值,那么它必须是父进程。
-
ZERO 如果返回码为0,那么一定是子进程
-
A positive value ,如果返回码是正值(或者子进程的PID),那么它的父进程
-
Negative , 如果返回码为负数,则子进程创建失败且不成功
如何使用Python fork?
Python 的 os 模块提供了一个函数 fork() 来创建子进程。要知道任何进程的 PID,请使用 os 模块中的函数 getpid()
import os
os.fork()
现在让我们做一些演示来了解发生了什么
DEMO 1:检查任何进程的进程ID
在下面的示例中,我们只是检查如何使用 getpid() 来获取当前进程的 PID。
import os
def demo1():
print('I am the only process, My PID:',os.getpid())
demo1()
这是输出:
DEMO 2:使用 fork() 创建一个子进程
在下面的示例中,我们在 fork() 调用之前和之后打印进程 ID。这意味着在 fork 之前,我们有一个进程,而在调用之后,我们有另一个新进程,总共有 2 个进程。
让我们检查以下代码段的输出
import os
def demo2():
print('Before calling fork(),PID: ', os.getpid())
os.fork()
print('After calling fork(), PID: ', os.getpid())
demo2()
这里是输出: -
shaikh@ubuntu:~/Jupyter/fork demos$ python3 demo2.py
Before calling fork(),PID: 6837
After calling fork(), PID: 6837
After calling fork(), PID: 6838
shaikh@ubuntu:~/Jupyter/fork demos$
如上所示,在 fork() 之前,我们只有一个 PID 为 6837 的进程,而在 fork 之后,我们有一个 PID 为 6838 的新进程。
Demo 3:识别父母和孩子
让我们看看,我们如何以编程方式识别父母和孩子。如上一节所述,如果 fork 的返回码为零,则为子进程,如果为正值,则为父进程。让我们在这里检查一下
import os
def demo3():
print('Before calling fork(),PID: ', os.getpid())
rc = os.fork()
if rc == 0:
print('I am child, PID: ', os.getpid())
os._exit(0)
elif rc > 0:
print('I am parent,PID:',os.getpid())
else:
print('Child process creation failed!!')
demo3()
输出
shaikh@ubuntu:~/Jupyter/fork demos$ python3 demo3.py
Before calling fork(),PID: 7316
I am parent,PID: 7316
I am child, PID: 7317
让我们了解上面发生了什么。在 fork 之前,我们只有一个 PID 为 7316 的进程,当它调用 fork() 时,我们得到了另一个进程。这些进程中的每一个都有不同的返回代码副本rc。父进程的 rc 为正值(子进程的 PID),子进程的 rc 等于零
Demo 4:让我们创建两个子进程
在下面的示例中,我们调用了 fork() 两次。
import os
def demo4():
#No fork, only one process
print('Before any fork, PID:',os.getpid())
#First fork
os.fork()
print('After first fork, PID:',os.getpid())
#Second fork
os.fork()
print('After second fork,PID:',os.getpid())
demo4()
输出如下:
shaikh@ubuntu:~/Jupyter/fork demos$ python3 demo4.py
Before any fork, PID: 7471
After first fork, PID: 7471
After first fork, PID: 7472
After second fork,PID: 7471
After second fork,PID: 7473
After second fork,PID: 7472
After second fork,PID: 7474
-
在第一次分叉之前只有一个进程
-
第一次分叉后,总进程为两个
-
第二次调用后,进程总数为四个
如果我们调用 fork 3 次,在评论部分猜猜将创建的进程数🙂
Demo 5: 让我们玩得开心
下面的示例将显示在 fork 调用之后,父子节点将拥有变量 num 的不同副本
import os
def demo5():
num = 0
rc = os.fork()
if rc > 0:
num = os.getpid()
print ('num: ',num)
demo5()
猜猜输出🙂
shaikh@ubuntu:~/Jupyter/fork demos$ python3 demo5.py
num: 7825
num: 0
所以在上面的代码中,只有父进程可以进入 if 语句,因为它有肯定响应代码,即子进程的 PID。由于孩子的 rc 是 ZERO,它仍然会有 num 的原始副本
结论
希望这是有趣而有趣的学习🙂。 fork 是在任何 Linux 操作系统中创建子进程的非常常见的方法。它被用于创建多个进程,最常见的用例是 Web 服务器,它在每个 http 请求上分叉一个新进程。
使用 fork 时要小心,并确保在完成任务后成功退出进程,否则内存和 cpu 使用率会很高,并可能造成内存泄漏情况,称为 fork 炸弹
所有的演示都在我的 GitHub 页面中。点击这里访问
参考文献
1.http://www2.cs.uregina.ca/~hamilton/courses/330/notes/unix/fork/fork.html
1.http://people.cs.pitt.edu/~aus/cs449/ts-lecture14.pdf
类似帖子
-
如何在 Linux 中管理进程所有关于进程
-
如何在 Linux 中监控 CPU 利用率cpu 利用率
-
如何使用 crontab 安排作业如何使用 crontab
更多推荐
所有评论(0)