fork() 和 exec() 的主要区别在于,
fork() 系统调用创建当前运行程序的克隆。原始程序在 fork() 函数调用之后继续执行下一行代码。克隆也开始执行下一行代码。
看看下面我从http://timmurphy.org/2014/04/26/using-fork-in-cc-a-minimum-working-example/得到的代码
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
int counter = 0;
pid_t pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n", ++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
return 0;
}
这个程序在fork()ing 之前声明了一个计数器变量,设置为零。在 fork 调用之后,我们有两个进程并行运行,都增加了它们自己版本的计数器。每个进程将运行完成并退出。因为进程并行运行,我们无法知道哪个会先完成。运行此程序将打印类似于下图所示的内容,但每次运行的结果可能会有所不同。
--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
child process: counter=1
parent process: counter=4
child process: counter=2
parent process: counter=5
child process: counter=3
--end of program--
child process: counter=4
child process: counter=5
--end of program--
exec() 系列系统调用将当前正在执行的进程代码替换为另一段代码。该进程保留其 PID,但它成为一个新程序。例如,考虑以下代码:
#include <stdio.h>
#include <unistd.h>
main() {
char program[80],*args[3];
int i;
printf("Ready to exec()...\n");
strcpy(program,"date");
args[0]="date";
args[1]="-u";
args[2]=NULL;
i=execvp(program,args);
printf("i=%d ... did it work?\n",i);
}
此程序调用execvp() 函数以将其代码替换为日期程序。如果代码存储在名为 exec1.c 的文件中,则执行它会产生以下输出:
Ready to exec()...
Tue Jul 15 20:17:53 UTC 2008
程序输出行 ―Ready to exec() 。 . . ‖ 并在调用 execvp() 函数后,将其代码替换为日期程序。请注意,行 ― 。 . .是否有效”不显示,因为此时代码已被替换。相反,我们看到执行“date -u”的输出。