Fork() 和 Wait() 与 C 中的 execvp()

Fork() and Wait() with execvp() in C

我正在尝试使用 fork 方法调用不同的程序并等待它完成, 我试图检查问题是什么,似乎等待函数没有等待 childReturns 并且它不打印答案。 (分配是循环比较方法直到 ctrl+c )

我调用的程序是比较 2 个字符串的比较器。

问题是等待函数不等待 child 编译是 GCC

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>

#define LINELEN (80)

char *mygets(char *buf, int len);
char *progName(char *prog);
int main(int argc, char *argv[])
{
    char *args[3];
    char str1[LINELEN + 1];
    char str2[LINELEN + 1];
    int childReturns;
    if (argc != 2)
        return -1;

    char *prog = progName(argv[1]);
    if (prog == NULL)
        return -1;
    args[0] = prog;
    while (1)
    {
        printf("Enter string:");
        if (mygets(str1, LINELEN) == NULL)
            break;
        printf("Enter  string:");
        if (mygets(str2, LINELEN) == NULL)
            break;
        args[1] = str1;
        args[2] = str2;
        int processId = fork();
        if (processId == 0)
            execvp(prog, args);
        else
        {
            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", WEXITSTATUS(childReturns));
        }
    }
    free(prog);
    return 0;
}
char *progName(char *prog)
{
    char *filePath = (char *)malloc(strlen(prog) + 3);
    if (!filePath)
        return NULL;
    strcpy(filePath, "./");
    strcat(filePath, prog);
    return filePath;
}

char *mygets(char *buf, int len)
{
    char *retval;

    retval = fgets(buf, len, stdin);
    buf[len] = '[=10=]';
    if (buf[strlen(buf) - 1] == 10) /* trim \r */
        buf[strlen(buf) - 1] = '[=10=]';
    else if (retval)
        while (getchar() != '\n')
            ; /* get to eol */

    return retval;
} ```

fork() 系统调用复制了母进程。生成的子进程和父进程将拥有自己的地址空间。所以子进程不能修改父进程的childReturns变量。

此外,wait(NULL) 等待子进程结束。

尝试链接这些行:

        if (processId == 0)
            execvp(prog, args);
        else

致这些:

        if (processId == 0) {
            execvp(prog, args);
            perror(prog);
            abort();
        } else

另请注意,WEXITSTATUS 仅在 WIFEXITTED() 为真时才有效。在这种情况下,当您的 child 处理 abort() 时,它不会成立。 所以

            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", 

需要更多的工作,例如:

     if (WIFEXITTED(childReturns)) {
         printf("Child code is %d\n", WEXITSTATUS(childReturns));
     } else if (WIFSIGNALED(childReturns)) {
         printf("Child killed by signal %d\n", WTERMSIG(childReturns);
     } else {
         printf("Child suffered %#x\n", childReturns);
     }

但是,您真正的问题是为什么 execvp() 会失败?仔细看看你的 args 数组有多大。它与文档相符吗?

正如 Jonathan Leffler 所说,问题出在 args 上,execvp() 需要 args 的数组最后 NULL

这解决了问题。

正确的代码:

    char str1[LINELEN + 1];
    char str2[LINELEN + 1];
    int childReturns = 1;
    if (argc != 2)
        return -1;

    char *prog = progName(argv[1]);
    if (prog == NULL)
        return -1;
    char *args[4];
    args[3] = NULL;
    args[0] = prog;
    while (1)
    {
        printf("Enter string:");
        if (mygets(str1, LINELEN) == NULL)
            break;
        printf("Enter  string:");
        if (mygets(str2, LINELEN) == NULL)
            break;
        args[1] = str1;
        args[2] = str2;
        int processId = fork();
        if (processId == 0)
        {
            execvp(prog, args);
        }
        else
        {
            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", WEXITSTATUS(childReturns));
        }
    }
    free(prog);
    return 0;```