【问题标题】:Restore stdin after a pipe管道后恢复标准输入
【发布时间】:2023-06-24 02:53:01
【问题描述】:

我使用标准输入和标准输出制作了一个管道进行通信,但在我的父亲进程中关闭标准输入后,我无法弄清楚如何恢复标准输入。

这是一个例子:

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

void readPBM(char *output)
{
    char tmp[1024];

    int fd[2] = {0,0};
    int pid;

    //Open the pipe for inter-process communication
    pipe(&fd[0]);

    //Fork and test if we are child or parent process
    pid = fork();
    if(pid) //Parent process
    {
        wait(NULL); //Wait for child's end
        close(fd[1]);//Close pipe's write stream
        close(0);//Close stdin
        dup(fd[0]);
        close(fd[0]);

        strcpy(output, "");// Init output at 0
        while(fgets(tmp, 1024, stdin) != NULL) //Put remainings entry in output
        {
            strcat(output, tmp);
        }
        strcat(output, "It works\n");
    }
    else if(pid == 0) //Child process
    {
        close(fd[0]);//Close pipe's read stream
        close(1);//Close stdout
        dup(fd[1]);//Duplicate stdin
        close(fd[1]);

        printf("A random string ...\n");
        exit(0);
    }
    else //Print error if fork failed
    {
        printf("Error creating a new process");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    int i, j;

    char *str = NULL;
    char c;

    str = malloc(512 * sizeof(char*));
    readPBM(str);

    printf("%s", str);

    c = getchar();
}

我尝试使用:int stdin_copy = dup(0) 保存标准输入,然后恢复它,但我的 getchar 不工作。
我也尝试使用freopen("/dev/stdin", "a", stdin),但它仍然不等待输入

【问题讨论】:

    标签: c pipe stdin


    【解决方案1】:

    使用 fdopen 似乎效果很好,所以这里是固定代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    void readPBM(char *output)
    {
        FILE* fp;
        char tmp[1024];
    
        int fd[2] = {0,0};
        int pid;
    
        //Open the pipe for inter-process communication
        pipe(&fd[0]);
    
        //Fork and test if we are child or parent process
        pid = fork();
        if(pid) //Parent process
        {
            wait(NULL); //Wait for child's end
            close(fd[1]);//Close pipe's write stream
    
            fp = fdopen(fd[0], "r");
    
            strcpy(output, "");// Init output at 0
            while(fgets(tmp, 1024, fp) != NULL) //Put remainings entry in output
            {
                strcat(output, tmp);
            }
            strcat(output, "It works\n");
            fclose(fp);
        }
        else if(pid == 0) //Child process
        {
            close(fd[0]);//Close pipe's read stream
            close(1);//Close stdout
            dup(fd[1]);//Duplicate stdin
            close(fd[1]);
    
            printf("A random string ...\n");
            exit(0);
        }
        else //Print error if fork failed
        {
            printf("Error creating a new process");
            exit(EXIT_FAILURE);
        }
    }
    
    int main(int argc, char *argv[])
    {
        int i, j;
    
        char *str = NULL;
        char c;
    
        str = malloc(512 * sizeof(char*));
        readPBM(str);
    
        printf("%s", str);
    
        c = getchar();
    }
    

    【讨论】: