fork和exec有什么区别?
当前回答
我认为Marc Rochkind的“高级Unix编程”中的一些概念有助于理解fork()/exec()的不同角色,特别是对于习惯了Windows CreateProcess()模型的人:
程序是保存在磁盘上常规文件中的指令和数据的集合。(摘自1.1.2程序、进程和线程)
.
为了运行程序,首先要求内核创建一个新进程,这是一个程序执行的环境。(也来自1.1.2程序、进程和线程)
.
It’s impossible to understand the exec or fork system calls without fully understanding the distinction between a process and a program. If these terms are new to you, you may want to go back and review Section 1.1.2. If you’re ready to proceed now, we’ll summarize the distinction in one sentence: A process is an execution environment that consists of instruction, user-data, and system-data segments, as well as lots of other resources acquired at runtime, whereas a program is a file containing instructions and data that are used to initialize the instruction and user-data segments of a process. (from 5.3 exec System Calls)
一旦你理解了程序和进程之间的区别,fork()和exec()函数的行为可以总结为:
Fork()创建当前进程的副本 Exec()将当前进程中的程序替换为另一个程序
(这基本上是paxdiablo更详细答案的简化版“傻瓜版”)
其他回答
理解fork()和exec()概念的主要例子是shell,用户通常在登录到系统后执行命令解释器程序。shell将命令行的第一个单词解释为命令名
对于许多命令,shell fork和子进程执行与名称相关的命令,将命令行上的剩余单词作为命令的参数。
shell允许三种类型的命令。首先,命令可以是 包含由源代码编译产生的目标代码的可执行文件(例如C程序)。其次,命令可以是一个可执行文件 包含shell命令行序列。最后,命令可以是一个内部shell命令。(而不是一个可执行文件ex->cd,ls等)
它们一起使用来创建一个新的子进程。首先,调用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
}
我认为Marc Rochkind的“高级Unix编程”中的一些概念有助于理解fork()/exec()的不同角色,特别是对于习惯了Windows CreateProcess()模型的人:
程序是保存在磁盘上常规文件中的指令和数据的集合。(摘自1.1.2程序、进程和线程)
.
为了运行程序,首先要求内核创建一个新进程,这是一个程序执行的环境。(也来自1.1.2程序、进程和线程)
.
It’s impossible to understand the exec or fork system calls without fully understanding the distinction between a process and a program. If these terms are new to you, you may want to go back and review Section 1.1.2. If you’re ready to proceed now, we’ll summarize the distinction in one sentence: A process is an execution environment that consists of instruction, user-data, and system-data segments, as well as lots of other resources acquired at runtime, whereas a program is a file containing instructions and data that are used to initialize the instruction and user-data segments of a process. (from 5.3 exec System Calls)
一旦你理解了程序和进程之间的区别,fork()和exec()函数的行为可以总结为:
Fork()创建当前进程的副本 Exec()将当前进程中的程序替换为另一个程序
(这基本上是paxdiablo更详细答案的简化版“傻瓜版”)
Fork()将当前进程拆分为两个进程。换句话说,你的线性程序突然变成了两个单独的程序,运行着一段代码:
int pid = fork();
if (pid == 0)
{
printf("I'm the child");
}
else
{
printf("I'm the parent, my child is %i", pid);
// here we can kill the child, but that's not very parently of us
}
这可能会让你大吃一惊。现在,两个进程执行了一段状态几乎相同的代码。子进程继承刚刚创建它的进程的所有代码和内存,包括从fork()调用刚刚停止的地方开始。唯一的区别是fork()返回的代码告诉你你是父类还是子类。如果你是父进程,返回值是子进程的id。
Exec更容易掌握一些,您只需告诉Exec使用目标可执行文件执行一个进程,并且不需要两个进程运行相同的代码或继承相同的状态。就像@Steve Hawkins说的,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;
}