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

发布于 2025-01-19 02:30:59 字数 1739 浏览 2 评论 0原文

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

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

问题是等待函数不等待子进程 编译是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] = '\0';
    if (buf[strlen(buf) - 1] == 10) /* trim \r */
        buf[strlen(buf) - 1] = '\0';
    else if (retval)
        while (getchar() != '\n')
            ; /* get to eol */

    return retval;
} ```

I'm am trying to use the fork method to call a different program and wait until it completes,
I tried to check what is the problem and it seems that the wait function doesn't wait to the childReturns and it makes doesn't print the answer.
(the assignment was to loop compare method until ctrl+c )

the program I call is a comparator that compares 2 strings.

the problem is that the wait func doesn't wait for the child
the compile is 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] = '\0';
    if (buf[strlen(buf) - 1] == 10) /* trim \r */
        buf[strlen(buf) - 1] = '\0';
    else if (retval)
        while (getchar() != '\n')
            ; /* get to eol */

    return retval;
} ```

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

放低过去 2025-01-26 02:30:59

尝试链接这些行:

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

对于这些:

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

另外,请注意,WEXITSTATUS 仅在 WIFEXITTED() 为 true 时才有效。在这种情况下,当你的孩子处理 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 数组有多大。与文档相符吗?

Try chaining these lines:

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

To these:

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

Also, note that WEXITSTATUS, is only valid if WIFEXITTED() is true. In this case, when your child process abort()'s, it will not be true.
So

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

needs a bit more work, like:

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

But, your real problem is why is execvp() failing? Look carefully at how big your args array is. Does it match the documentation?

演出会有结束 2025-01-26 02:30:59

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

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

fork() system call duplicates the mother process. The resulting child process and the parent process will have their own address spaces. So child process can not modify childReturns variable of the parent.

Additionally, wait(NULL) waits for child processes to end.

一花一树开 2025-01-26 02:30:59

正如 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;```

As Jonathan Leffler said the problem was with the args, execvp() needs that the array off args has in the end NULL.

and that fixed the problem.

the Right code :

    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;```
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文