进程、fork、管道程序……我哪里出错了?

Processes, fork, pipes program...Where am I going wrong?

我在 Unix 中工作,我正在尝试编写一个 .c 文件来执行以下操作:

对于每个命令行参数,主进程将启动一个子进程(类型 A)。

A 进程将尝试在新的子进程(类型 B)中使用 exec 函数之一执行接收到的参数。

如果失败,类型 A 的进程将使用管道通道将 exec 调用生成的错误代码(errno 值)发送到其父进程。

成功后,进程 A 将等待类型 B 的进程,一旦完成,它将使用相同的管道通道将零代码传输给其父进程。

无论执行成功与否,主进程都会打印每个参数。仅对于失败的执行,错误接收代码也会被打印出来。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char const *argv[]) {
        int c2p[2], g2c[2];
        int i;
        char n[100];
        int *stat;
        for (i = 0; i < argc; i++ ) {
                pipe(c2p);
                pipe(g2c);
                if (fork() == 0) {
                        //child code
                        if (fork() == 0) {
                                //grandchild code
                                if (execlp("argv[i]", "argv[i]", NULL) == -1) {
                                        write(g2c[1], errno, sizeof(int));
                                } else {
                                        write(g2c[1], 0, sizeof(int));
                                }
                        }
                        wait(0);
                        read(g2c[0], n, 10);
                        write(c2p[1], n, 10);
                        exit(0);
                }
                read(c2p[0], &stat, sizeof(int));
                if (*stat !=0) {
                        printf("Not succsesful: %s  %d\n", argv[i], *stat);
                } else {
                        printf("Succes! %s\n", argv[i]);
                }
        }

        return 0;
}

两个问题:

  • 你不能那样写一个整数,write 需要一个 pointer,所以 int n; ...; write(fd, &n, sizeof n);
  • execlp replaces 调用它的进程,这意味着如果它有效,你将永远不会向管道写入零,因为孙子已被 execlp() 程序替换正在

如下更改您的代码,这对您有用:

int main(int argc, char const *argv[])
{
    int c2p[2];
    int i;
    int stat;

    for (i = 1; i < argc; i++ ) {
            pipe(c2p);
            if (fork() == 0) {
                    //child code
                    if (fork() == 0) {
                            //grandchild code
                            if (execlp(argv[i], argv[i], NULL) == -1)
                                 exit(errno);
                    }
                    wait(&stat);
                    write(c2p[1], &stat, sizeof(stat));
                    exit(0);
             }
             read(c2p[0], &stat, sizeof(int));
             if (stat != 0)
                   printf("Not succsesful: %s %d\n", argv[i], stat);
             else
                   printf("Succes! %s\n", argv[i]);
    }
}

如您在我的代码中所见:

  • stat 必须是整数而不是指针
  • 你将 argv[i] 作为参数而不是 "argv[i]" 传递给 execlp
  • 您退出状态代码以通过 grandchild 的状态(您也可以 此技术在 child)
  • 从 1 开始执行循环,因为 argv[0] 是您的程序名称。
  • 在使用 exec 系列函数后永远记住你的源代码 进程替换为您调用的程序,因此您无法在成功后执行 运行。