进程
进程(process)是正在运行的程序的实例,但一个程序可能会产生多个进程。比如,打开 Chrome 浏览器程序,它可能会产生多个进程,主程序需要一个进程,一个网页标签需要一个进程,一个插件也需要一个进程,等等。
每个进程都有自己的地址空间,内存,数据栈以及其他记录其运行状态的辅助数据,不同的进程只能使用消息队列、共享内存等进程间通讯(IPC)方法进行通信,而不能直接共享信息。
fork()
在介绍 Python 的进程编程之前,让我们先看看 Unix/Linux 中的 fork
函数。在 Unix/Linux 系统中,fork
函数被用于创建进程。这个函数很特殊,对于普通的函数,调用它一次,返回一次,但是调用 fork
一次,它返回两次。事实上,fork
函数创建了新的进程,我们把它称为子进程,子进程几乎是当前进程(即父进程)的一个拷贝:它会复制父进程的代码段,堆栈段和数据段。
对于父进程,fork
函数返回了子进程的进程号 pid,对于子进程,fork
函数则返回 0
,这也是 fork
函数返回两次的原因,根据返回值,我们可以判断进程是父进程还是子进程。
下面我们看一段 C 代码,它展示了 fork 的基本使用:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int pid;
pid = fork(); // 使用 fork 函数
if (pid < 0) {
printf("Fail to create process\n");
}
else if (pid == 0) {
printf("I am child process (%d) and my parent is (%d)\n", getpid(), getppid());
}
else {
printf("I (%d) just created a child process (%d)\n", getpid(), pid);
}
return 0;
}
其中,getpid
用于获取当前进程号,getppid
用于获取父进程号。
事实上,Python 的 os 模块包含了普遍的操作系统功能,该模块也提供了 fork
函数,把上面的代码改成用 Python 来实现,如下:
import os
pid = os.fork()
if pid < 0:
print 'Fail to create process'
elif pid == 0:
print 'I am child process (%s) and my parent is (%s).' % (os.getpid(), os.getppid())
else:
print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)
运行上面的代码,产生如下输出:
I (86645) just created a child process (86646).
I am child process (86646) and my parent is (86645).
需要注意的是,虽然子进程复制了父进程的代码段和数据段等,但是一旦子进程开始运行,子进程和父进程就是相互独立的,它们之间不再共享任何数据。