使用 bin/time 时 Execv 不工作

Execv not working when using bin/time

当我尝试执行 /bin/time /bin/echo Hello world 时我的程序出现问题,我没有得到任何输出。我知道这个示例代码有效 例如 /bin/date 或 /bin/echo 我认为它也应该与时间一起使用但它不是

int main(int argc, char * argv []) {    
    int err = 1;
    char *array[3] = {"/bin/time", "/bin/echo", "Hello World"};
    pid_t childPIorZero = fork();

    if (childPIorZero < 0){
        perror("fork() error");
        exit(-1);                        
    }
    if (childPIorZero != 0){
        printf("I'm the parent %d, my child %d\n",getpid(),childPIorZero);
        wait(NULL); 
    }           
    else{
         printf("I'm the child %d, my parent %d\n",getpid(), getppid());
         err = execv(array[0], array);
         printf("error = %d\n", err);
         printf("%s\n", strerror(err));
    }

    return 0;
}

我虽然问题是我以错误的方式将参数传递给 execv,但它适用于 echo bin 和 date bin,所以我不知道哪里出了问题。输出如下:

I'm the parent 28001, my child 28011
I'm the child 28011, my parent 28001
error = -1
Unknown error -1

此代码 运行 在 Ubuntu 16.04 LTS VM 上运行 Mac 运行 macOS Sierra 10.12.4(以及 运行 在 macOS 上也可以)。

#define _XOPEN_SOURCE 700
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    char *array[] = { "/usr/bin/time", "/bin/echo", "Hello World", 0 };
    pid_t childPIorZero = fork();

    if (childPIorZero < 0)
    {
        perror("fork() error");
        exit(-1);
    }
    if (childPIorZero != 0)
    {
        printf("I'm the parent %d, my child %d\n", getpid(), childPIorZero);
        int status;
        int corpse;
        while ((corpse = wait(&status)) != -1)
            printf("PID %d exited with status 0x%.4X\n", corpse, status);
    }
    else
    {
        printf("I'm the child %d, my parent %d\n", getpid(), getppid());
        execv(array[0], array);
        int errnum = errno;
        fprintf(stderr, "(%d) %s\n", errnum, strerror(errnum));
        exit(1);
    }

    return 0;
}

问题中代码的主要变化包括:

  • 正在更改 time 可执行文件的位置。
  • 将空指针添加到 array 的末尾。
  • execv() 失败后报告 stderr 上的错误,而不是 stdout
  • 报告来自 errno 的错误,而不是来自 execv() 的 return 值,如果 return 根本没有,它总是 -1
  • 如果 execv() 失败,将以错误状态退出。
  • 循环直到没有 children 剩余(在有趣的情况下,一个进程可以继承 children 同一进程的前一个化身分叉 - 大多数情况下,你没有担心它,但我总是使用循环等待)。
  • 报告 child 的退出状态。

在 Ubuntu 上,我编译了:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
>     -Wstrict-prototypes -Wold-style-definition ev11.c -o ev11
$ ./ev11
I'm the parent 25129, my child 25130
I'm the child 25130, my parent 25129
Hello World
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 1620maxresident)k
8inputs+0outputs (1major+66minor)pagefaults 0swaps
PID 25130 exited with status 0x0000
$

我在 macOS 上使用相同的编译命令行(当然是不同的编译器)并得到:

$ ./ev11
I'm the parent 3220, my child 3221
I'm the child 3221, my parent 3220
Hello World
        0.00 real         0.00 user         0.00 sys
PID 3221 exited with status 0x0000
$