fork和exec有什么区别?
当前回答
Fork()创建当前进程的副本,在Fork()调用之后的新子进程中执行。在fork()之后,除了fork()函数的返回值外,它们是相同的。(详情请参阅RTFM。)这两个进程可以进一步分离,其中一个进程不能干扰另一个进程,除非可能通过任何共享的文件句柄。
Exec()将当前进程替换为新进程。它与fork()无关,只是当需要启动不同的子进程,而不是替换当前进程时,exec()通常会在fork()之后执行。
其他回答
fork ():
它创建正在运行的进程的副本。正在运行的进程称为父进程,新创建的进程称为子进程。区分两者的方法是通过查看返回值:
Fork()返回父进程中子进程的标识符(pid) Fork()在子对象中返回0。
exec ():
它在一个流程中启动一个新流程。它将一个新程序加载到当前进程中,替换现有的程序。
Fork () + exec():
当启动一个新程序时,首先fork(),创建一个新进程,然后exec()(即加载到内存并执行)它应该运行的程序二进制。
int main( void )
{
int pid = fork();
if ( pid == 0 )
{
execvp( "find", argv );
}
//Put the parent to sleep for 2 sec,let the child finished executing
wait( 2 );
return 0;
}
它们一起使用来创建一个新的子进程。首先,调用fork创建当前进程(子进程)的副本。然后,在子进程内部调用exec,用新进程“替换”父进程的副本。
这个过程是这样的:
child = fork(); //Fork returns a PID for the parent process, or 0 for the child, or -1 for Fail
if (child < 0) {
std::cout << "Failed to fork GUI process...Exiting" << std::endl;
exit (-1);
} else if (child == 0) { // This is the Child Process
// Call one of the "exec" functions to create the child process
execvp (argv[0], const_cast<char**>(argv));
} else { // This is the Parent Process
//Continue executing parent process
}
Fork创建调用进程的副本。 一般遵循结构
int cpid = fork( );
if (cpid = = 0)
{
//child code
exit(0);
}
//parent code
wait(cpid);
// end
(对于子进程文本(代码),数据,堆栈与调用进程相同) 子进程执行if块中的代码。
EXEC用新进程的代码、数据和堆栈替换当前进程。 一般遵循结构
int cpid = fork( );
if (cpid = = 0)
{
//child code
exec(foo);
exit(0);
}
//parent code
wait(cpid);
// end
(exec调用后,Unix内核清除子进程的文本,数据,堆栈,并填充与foo进程相关的文本/数据) 因此子进程使用不同的代码(foo的代码{与父进程不相同})
Fork()创建当前进程的副本,在Fork()调用之后的新子进程中执行。在fork()之后,除了fork()函数的返回值外,它们是相同的。(详情请参阅RTFM。)这两个进程可以进一步分离,其中一个进程不能干扰另一个进程,除非可能通过任何共享的文件句柄。
Exec()将当前进程替换为新进程。它与fork()无关,只是当需要启动不同的子进程,而不是替换当前进程时,exec()通常会在fork()之后执行。
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()之前声明了一个计数器变量,设为0。在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()函数将其代码替换为date程序。如果代码存储在名为exec1.c的文件中,则执行它会产生以下输出:
Ready to exec()...
Tue Jul 15 20:17:53 UTC 2008
程序输出一行-Ready to exec()…‖并且在调用execvp()函数后,将其代码替换为date程序。注意这一行-…它是否工作‖不显示,因为在这一点上,代码已被替换。相反,我们看到执行-date -u.‖的输出