2011-08-23 62 views
6

我试图用fork和execlp程序,其中父地址空间替换为“ls”命令。叉和Execlp

#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(); 
    } 
} 

当我执行程序的孩子

printf("\nStill I am the child\n"); 

的最后一行不打印。为什么?

回答

16

exec家庭功能在成功时不会返回。

http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html

功能的高管家属应带一个新的进程映像替换当前的进程映像。新图像应该由一个称为新过程映像文件的常规可执行文件构建。由于调用过程映像被新过程映像覆盖,因此成功执行将不会返回。

如果其中一个exec函数返回到调用过程映像,则发生错误;返回值应为-1,并应设置errno来指示错误。

4

exec函数不会仅执行您的命令。他们实际上会用您选择的可执行文件替换进程的执行上下文(您的情况为/bin/ls)。

换句话说,由于ls函数以终止其进程(“退出”或返回主函数或其它)结束,所以在执行ls时,您的子进程将被终止。

实际上,你可以用这个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. 
    } 
0

功能execlp()之后没有得到按execlp 因此您的printf()语句的文件执行“我仍然是孩子“不会被执行......!

-3
  1. 您正在进程ID int类型,但实际上,存储进程id,你应该当您使用exec类的函数调用整个进程的地址空间替代调用过程中使用pid_t
  2. 。所以,现在最后printf说法是不存在的新的过程,事实上,即使是进程的进程ID也不会改变
+0

几个好点,但在新的过程中,pid肯定是不同的。另外,如果exec成功,exec只会替换进程,否则它将在exec调用之后继续 – techdude

1

原因很简单:EXEC()如果错误已经具备的功能只返回发生。对于相同的请参阅exec()函数的手册页。

什么时候执行exec()函数调用到底正在发生:

EXECL()不创建一个新的进程 - 它修改 威斯和相关的内容 - 此外,执行上下文 也被修改。

  • 旧执行上下文不再使用 - 创建新的执行上下文。
    • 一个新的,新的上下文为新加载的应用程序创建和 控制传递给scheduler-调度恢复同孩子 工艺与新获得的执行上下文 - 使用此,跳转 执行到入口新应用程序的一个点,在用户空间中 - 新应用程序开始在相同的子进程中执行。
      • 系统堆栈被新的hw上下文覆盖 在用户空间中恢复新程序的main()。
    • 子进程中的旧应用程序的执行上下文和代码/数据/堆/堆栈被完全销毁 - 不再可用。
    • 当execve()或execl()无法在当前进程中加载​​ 新应用程序时,execve()或execl()将返回到当前进程的相同应用程序/代码 --意思是唯一的时间 当完成execv()/ execl()/调用系列时出现 错误时,execv()/ execvl()或系列调用将返回。

注意:您必须对 错误/错误代码验证的exec()系列系统调用的API的返回值 - 基于误差/错误代码, 您可以终止当前进程或采取一些其他 操作。