c中的Exec函数在应该返回时没有返回-1

c中的Exec函数在应该返回时没有返回-1,c,fork,exec,C,Fork,Exec,我正在使用execv函数运行一个名为code.x的程序。 code.x有一部分通过断言保证其失败。 我运行execl的代码是: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <string.h>

我正在使用execv函数运行一个名为code.x的程序。 code.x有一部分通过断言保证其失败。 我运行execl的代码是:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h> 
#include <errno.h>
#include <string.h>

int main()
{
    pid_t pid;
    char *args[] = { "./code.x",NULL };
    pid = fork();
    if (pid > 0) {
        wait(NULL);
        printf("%s\n", strerror(errno));
        printf("done\n");
    }
    else if (pid == 0) {
        printf("%s\n", strerror(errno));
        execv(args[0], args);
        printf("should fail");
    }
    else {
        printf("forkfail");
    }
    return 1;
}

从不打印“应失败”,WEXITSTATUS(状态)显示退出状态为0。

execv
成功完成其工作。进程
/code.x
已执行,然后由于断言而退出

exec函数族不关心进程的返回值。一旦进程启动,调用进程就会有效地终止并消失

只有由于某种原因无法启动进程时,Exec才会返回。具体而言,只有这些错误(取自手册页)才会导致exec返回并将
errno
设置为以下值之一:

  • E2BIG
    环境(envp)和参数列表(argv)中的总字节数太大

  • EACCES
    对文件名路径前缀或脚本解释器名称的组件的搜索权限被拒绝。(另见路径_决议(7))

  • EACCES
    文件或脚本解释器不是常规文件

  • EACCES
    文件、脚本或ELF解释器的执行权限被拒绝

  • EACCES
    文件系统在noexec上装载

  • EAGAIN
    (从Linux 3.1开始) 在使用set*UID()调用之一更改了其真实UID后,调用方过去和现在都高于其RLIMIT_NPROC资源限制(请参阅 setrlimit(2))。有关此错误的更详细解释,请参见注释

  • EFAULT
    filename或向量argv或envp中的一个指针指向可访问地址空间之外

  • EINVAL
    一个ELF可执行文件有多个PT_INTERP段(即,试图命名多个解释器)

  • EIO
    发生I/O错误

  • EISDIR
    ELF解释器是一个目录

  • elibad
    ELF解释器的格式不可识别

  • ELOOP
    解析脚本或ELF解释器的文件名或名称时遇到太多符号链接

  • ELOOP
    递归脚本解释过程中达到了最大递归限制(请参见上文的“解释器脚本”)。在Linux3.8之前 此案例产生的错误为ENOEXEC

  • EMFILE
    已达到每个进程对打开的文件描述符数量的限制

  • enametolong
    文件名太长

  • ENFILE
    已达到系统范围内打开文件总数的限制

  • enoint
    文件名、脚本或ELF解释器不存在,或者找不到文件或解释器所需的共享库

  • ENOEXEC
    可执行文件的格式不可识别、架构错误或存在其他格式错误,这意味着无法执行

  • ENOMEM
    内核内存不足

  • ENOTDIR
    文件名或脚本或ELF解释器的路径前缀的组件不是目录

  • EPERM
    文件系统是以nosuid装载的,用户不是超级用户,并且文件设置了set user ID或set group ID位

  • EPERM
    正在跟踪进程,用户不是超级用户,并且文件已设置了设置用户ID或设置组ID位

  • EPERM
    A“能力哑”应用程序将无法获得可执行文件授予的全部允许能力。见能力(7)

  • ETXTBSY
    指定的可执行文件已被一个或多个进程打开以供写入


exec函数系列将调用进程替换为从可执行文件加载的初始状态的新程序。只有当替换失败时,它们才能失败,例如,由于请求的文件不存在或调用用户没有访问/执行该文件的权限


如果您正在调用的程序
/code.x
中发生断言失败,这已经远远超过了
execv
可能失败的点;此时,执行
execv
的原始程序状态不再存在,因为它已被替换。父进程将通过
wait
-系列函数看到它退出,并且可以检查
wait
-系列函数报告的状态,以确定它退出的原因。

exec*
函数在程序开始运行时成功。你的程序确实开始运行了

断言失败导致程序中止,并发出信号退出。Linux解释说:

WEXITSTATUS(wstatus)

返回子级的退出状态。这包括子级在调用
exit(3)
\u exit(2)
或as时指定的状态参数的最低有效8位
main()
中返回语句的参数只有当
WIFEXITED
返回true时,才应使用此宏。

如果您没有检查
WIFEXITED(status)
是否为真,则
WEXITSTATUS(status)
垃圾


相反,请检查
WIFSIGNALED(status)
,如果为true,则获取信号-
WTERMSIG(status)
,该信号应等于
SIGABRT

Exec函数系列将现有进程映像替换为新进程映像。这就是为什么在生成另一个进程之前需要fork,因为当前运行的进程是完全可重用的
Success
code.x: code.c:15: main: Assertion '0 == 1' failed.
Success
done
printf("should fail");