Linux Fork 和 Execlp
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7156338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fork and Execlp
提问by user567879
I trying a program with fork and execlp where parent address space is replaced with "ls" command.
我尝试了一个带有 fork 和 execlp 的程序,其中父地址空间被替换为“ls”命令。
#include<stdio.h>
main()
{
int pid,j=10,fd;
pid=fork();
if(pid==0)
{
printf("\nI am the child\n");
execlp("/bin/ls","ls",NULL);
printf("\nStill I am the child\n");
}
else if (pid > 0)
{
printf("\n I am the parent\n");
wait();
}
}
When I execute the program the last line of child
当我执行程序时,孩子的最后一行
printf("\nStill I am the child\n");
is not printed. Why?
不打印。为什么?
采纳答案by hari
exec
family functions do not return when successful.
exec
family 函数在成功时不会返回。
http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html
http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html
The exec family of functions shall replace the current process image with a new process image. The new image shall be constructed from a regular, executable file called the new process image file. There shall be no return from a successful exec, because the calling process image is overlaid by the new process image.
If one of the exec functions returns to the calling process image, an error has occurred; the return value shall be -1, and errno shall be set to indicate the error.
exec 系列函数应使用新的进程映像替换当前进程映像。新映像应由称为新进程映像文件的常规可执行文件构建。成功的 exec 不会返回,因为调用进程映像被新进程映像覆盖。
如果 exec 函数之一返回调用进程映像,则发生错误;返回值应为 -1,并且应设置 errno 以指示错误。
回答by rahmu
exec
functions will not merely execute your command. They will actually replace the execution context of the process by your selected executable (in your case /bin/ls
).
exec
函数不仅会执行您的命令。他们实际上会用您选择的可执行文件(在您的情况下/bin/ls
)替换流程的执行上下文。
In other words, since the ls
function ends by terminating its process (thorugh 'exit' or returning the main function or whatever), your child process will be killed at the end of the execution of ls
.
换句话说,由于ls
函数以终止其进程(通过“退出”或返回主函数或其他方式)结束,因此您的子进程将在ls
.
You can actually use this printf call to print some errors, for instance:
您实际上可以使用此 printf 调用来打印一些错误,例如:
if(pid==0)
{
printf("\nI am the child\n");
execlp("/bin/ls","ls",NULL);
printf("\nError: Could not execute function %s\n", "/bin/ls");
_exit(0); //make sure you kill your process, it won't disappear by itself.
}
回答by Subbu
after the function execlp() does not get executed as per the documentation of execlp hence your printf() statement "Still I'm the child" does not get executed ...!!
在函数 execlp() 没有按照 execlp 的文档执行之后,因此你的 printf() 语句“我还是孩子”没有被执行......!
回答by user2670535
- You are taking process id as
int
type but actually , to store process id you should usepid_t
- When you use exec family function the entire address space of called process replaces the calling process. So,now the last
printf
statement is not there in the new process , actually even the process id of the process is also not changed
- 您将进程 ID 作为
int
类型,但实际上,要存储您应该使用的进程 IDpid_t
- 当您使用 exec 系列函数时,被调用进程的整个地址空间将替换调用进程。所以,现在
printf
新进程中没有最后一条语句,实际上甚至进程的进程ID也没有改变
回答by Prashanth Reddy D
The reason is simple : The exec() functions only return if an error has have occurred. For the same refer man pages of exec() functions.
原因很简单:exec() 函数仅在发生错误时返回。对于相同的参考手册页 exec() 函数。
What exactly is happening when exec() functions are called :
调用 exec() 函数时到底发生了什么:
execl() does not create a new process - it modifies the VADS and associated contents - in addition, execution context is also modified.
execl() 不会创建新进程——它会修改 VADS 和相关内容——此外,还会修改执行上下文。
- old execution context is no longer used - a new execution context is created.
- a new, fresh context is created for the newly loaded application and
control is passed to the scheduler- scheduler resumes the same child
process with the newly available execution context - using this, a jump
is executed to the entry point of the new application, in user-space -
the new application starts executing in the same child process.
- system stack is overwritten with new hw context for resuming the main() of the new program in user-space.
- execution context and code/data/heap/stack of old application in the child process are completely destroyed - no longer available.
- only time execve() or execl() will return to the same application/code of the current process is when execve() or execl() fails to load a new application in the current process - meaning, the only time execv()/execvl() or family of calls will return is when there is error in completing execv()/execl()/family of calls.
- a new, fresh context is created for the newly loaded application and
control is passed to the scheduler- scheduler resumes the same child
process with the newly available execution context - using this, a jump
is executed to the entry point of the new application, in user-space -
the new application starts executing in the same child process.
- 不再使用旧的执行上下文 - 创建一个新的执行上下文。
- 为新加载的应用程序创建一个新的上下文,并将控制权传递给调度程序 - 调度程序使用新可用的执行上下文恢复相同的子进程 - 使用这个,跳转到新应用程序的入口点,在用户空间 - 新应用程序开始在同一个子进程中执行。
- 系统堆栈被新的硬件上下文覆盖,用于在用户空间中恢复新程序的 main()。
- 子进程中旧应用程序的执行上下文和代码/数据/堆/堆栈被完全破坏 - 不再可用。
- 只有当 execve() 或 execl() 无法在当前进程中加载新应用程序时,execve() 或 execl() 才会返回到当前进程的相同应用程序/代码 - 意思是,唯一的时间 execv()/ execvl() 或调用系列将在完成 execv()/execl()/调用系列时出现错误时返回。
- 为新加载的应用程序创建一个新的上下文,并将控制权传递给调度程序 - 调度程序使用新可用的执行上下文恢复相同的子进程 - 使用这个,跳转到新应用程序的入口点,在用户空间 - 新应用程序开始在同一个子进程中执行。
Note: you must validate the return value of exec() family system call APIs for errors / error codes - based on the error/error codes, you may terminate the current process or take some other action.
注意:您必须验证 exec() 系列系统调用 API 的错误/错误代码的返回值 - 基于错误/错误代码,您可以终止当前进程或采取其他一些操作。