【问题标题】:How can I use pipes to send a flag to a child process?如何使用管道向子进程发送标志?
【发布时间】:2021-06-14 01:54:57
【问题描述】:

我需要编写一个程序来请求一个整数,将输入通过管道传递给子进程,在子进程中进行平方,再通过管道返回父进程,然后再请求另一个输入。

我可以在没有循环的情况下执行此操作,但我终其一生都无法弄清楚我需要调用 fork() 和 read() 的顺序。

这是我所拥有的:

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

int main(void){

    int psocket[2];
    int csocket[2];
    int csig[2];
    int sig = 0;

    pid_t child;

    if(read(csig[0], &sig, sizeof(int)) == -1)
        perror("reading signal");

    if(sig){
        int square;

        if(read(csocket[0], &square, sizeof(int))==-1)
            perror("read to child");

        square = square * square;

        if(write(psocket[1], &square, sizeof(int))==-1)
            perror("write to parent");

        return 0;
    }
    
    while(1){
        int value;
        sig = 1;

        printf(">> ");
        scanf("%d", &value);

        if(value ==0)
            break;

        if(write(csocket[1], &value, sizeof(int))==-1)
            perror("write to child");
        if(write(csig[1], &value, sizeof(int))==-1)
            perror("write to signal");

        child = fork();
        wait(NULL);

        if(read(psocket[0], &value, sizeof(int))==-1)
            perror("read to parent");

        printf("\n>> %d\n", value);
    } 

    return 0;
}

但我在尝试读/写 csig 管道时遇到错误

reading signal: Bad file descriptor
>> 32 //entering a value to test
 write to signal: Bad file descriptor

此时我完全迷失了。还有其他方法可以解决这个问题吗?有什么明显的我做错了吗?

编辑:

我意识到我忘了调用 pipe()

我加了

if ((pipe(psocket) < 0) || (pipe(csocket) < 0) || (pipe(csig) < 0)) {
        perror("opening stream socket pair");
        exit(10);
}

变量初始化后,现在程序挂起。

【问题讨论】:

  • 您正在使用未初始化的变量。
  • @shawn 已修复,我认为。
  • 您现在(假设我正确解释了您的编辑:如果您实际编辑问题并添加代码会很方便)创建一个管道并立即尝试从中读取。由于没有写入者,读取将永远阻塞。
  • 我此时已将其隔离为一个问题,但这让我仍然完全不知道如何解决这个问题。如果我无法调用读取尚未写入的管道,如何让子进程知道它是子进程?如果我在循环之前调用 fork,那么我如何递归调用新进程?
  • 孩子会根据fork()的返回值知道它是一个孩子。您应该每个程序只分叉一次,而不是每个输入一次。

标签: c linux pipe fork posix


【解决方案1】:

我意识到我可以递归调用 main() 进程,问题解决了

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

int main(void){
    int psocket[2];
    int csocket[2];
    pid_t child;

    if(pipe(psocket) < 0 || pipe(csocket) < 0)
        perror("pipe");

    child = fork();
    if(child < 0)
        perror("fork");

    if(child == 0){
        int value = 0;

        if(read(csocket[0], &value, sizeof(int)) < 0)
            perror("read child");

        value = value * value;

        if(write(psocket[1], &value, sizeof(int)) < 0)
            perror("write parent");
    }
    else if (child){
        int value = 0;

        printf(">> ");
        scanf("%d", &value);


        if(write(csocket[1], &value, sizeof(int)) < 0)
            perror("write child");

        wait(NULL);

        if(read(psocket[0], &value, sizeof(int)) < 0)
            perror("read parent");

        printf("Squared: %d\n", value);

        main();
    }

    return 0;
}

【讨论】:

  • 请注意,如果这是一项教育任务,则此解决方案可能不会给出满分,因为它不会与子进程保持持久对话,而是在泄漏堆栈和 FD 时不断分叉新进程.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-19
  • 2020-01-06
  • 1970-01-01
  • 2019-11-19
  • 2012-05-16
相关资源
最近更新 更多