简体   繁体   English

Fork和Execlp

[英]Fork and Execlp

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? 为什么?

exec family functions do not return when successful. exec系列函数在成功时不返回。

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. exec系列函数应使用新的过程映像替换当前过程映像。 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. 成功的exec不会返回,因为调用过程映像被新的过程映像覆盖。

If one of the exec functions returns to the calling process image, an error has occurred; 如果其中一个exec函数返回到调用进程映像,则发生错误; the return value shall be -1, and errno shall be set to indicate the error. 返回值应为-1,并设置errno以指示错误。

exec functions will not merely execute your command. exec函数不仅会执行您的命令。 They will actually replace the execution context of the process by your selected executable (in your case /bin/ls ). 它们实际上会用您选择的可执行文件替换进程的执行上下文(在您的case /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. 
    }

The reason is simple : The exec() functions only return if an error has have occurred. 原因很简单:exec()函数仅在发生错误时才返回。 For the same refer man pages of exec() functions. 对于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. 为新加载的应用程序创建一个新的,全新的上下文,并将控制传递给调度程序 - 调度程序使用新的可用执行上下文恢复相同的子进程 - 使用此操作,执行跳转到新应用程序的入口点, user-space - 新应用程序在同一子进程中开始执行。
      • system stack is overwritten with new hw context for resuming the main() of the new program in user-space. 系统堆栈被新的hw上下文覆盖,用于在用户空间中恢复新程序的main()。
    • 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. 只有当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的返回值以查找错误/错误代码 - 根据错误/错误代码,您可以终止当前进程或采取其他一些操作。

函数execlp()没有按照execlp的文档执行,因此你的printf()语句“我仍然是孩子”不会被执行...... !!

  1. You are taking process id as int type but actually , to store process id you should use pid_t 您将进程ID作为int类型,但实际上,要存储进程ID,您应该使用pid_t
  2. When you use exec family function the entire address space of called process replaces the calling process. 当您使用exec系列函数时,被调用进程的整个地址空间将替换调用进程。 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 所以,现在最后一个printf语句不在新进程中,实际上甚至进程的进程id也没有改变

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM