子进程在协进程中读取后挂起

标签 c linux ipc pipe

我正在使用管道编写一个协进程程序。当 child 读取一些数据、处理它并输出它时,它工作得很好。但是当我读取所有数据并处理它时,它只是悬而未决。有人有什么想法吗?谢谢。

这是源代码:

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


int main()
{
    #define MAXSIZE 1024

    char workload[MAXSIZE];
    char result[MAXSIZE];
    workload[strlen(workload)] = EOF;
    int workload_size = strlen(workload);

    int fd1[2], fd2[2];
    int n;
    pid_t pid;
    if (pipe(fd1) < 0 || pipe(fd2) < 0) {
        fprintf(stderr, "pipe error: %s\n", strerror(errno));
        exit(1);
    }

    if ((pid = fork()) < 0) {
        fprintf(stderr, "fork error: %s\n", strerror(errno));
        exit(1);
    } else if (pid > 0) {
        close(fd1[0]);
        close(fd2[1]);
        while(fgets(workload, MAXSIZE, stdin) != NULL)
        {
            workload_size = strlen(workload);
            if (write(fd1[1], workload, workload_size) != workload_size) {
                fprintf(stderr, "write to pipe error: %s\n", strerror(errno));
                exit(1);
            }

            if ((n = read(fd2[0], result, MAXSIZE)) < 0) {
                fprintf(stderr, "read from pipe error: %s\n", strerror(errno));
                exit(1);
            }

            if (n == 0) {
                fprintf(stderr, "child closed the pipe\n");
                exit(1);
            }

            result[n] = 0;

            if (puts(result) == EOF) {
                fprintf(stderr, "fputs error\n");
                exit(1);
            }
        }
    } else {
        close(fd1[1]);
        close(fd2[0]);
        if (fd1[0] != STDIN_FILENO) {
            if (dup2(fd1[0] ,STDIN_FILENO) != STDIN_FILENO) {
                fprintf(stderr, "dup2 error to stdin.\n");
                exit(1);
            }
            close(fd1[0]);
        }
        if (fd2[1] != STDOUT_FILENO) {
            if (dup2(fd2[1] ,STDOUT_FILENO) != STDOUT_FILENO) {
                fprintf(stderr, "dup2 error to stdout.\n");
                exit(1);
            }
            close(fd2[1]);
        }

        if (execl("./a.out", "a.out", NULL) < 0) {
            fprintf(stderr, "execl error: %s\n", strerror(errno));
            exit(1);
        }
        exit(0);
    }

    return 0;
}

这是a.out的源代码,它与此配合良好:

#include <stdio.h>
#include <string.h>

int main()
{
    #define MAXSIZE 1024
    char x[MAXSIZE];
    int n;
    while(scanf("%s", x) != EOF)
    {
        printf("len:%d %s", strlen(x), x);
        fflush(stdout);
    }
    return 0;
}

但当我编写这样的代码时,它似乎只是悬而未决:

#include <stdio.h>
#include <string.h>

int main()
{
    #define MAXSIZE 1024
    char x[MAXSIZE];
    int n;
    while(scanf("%s", x) != EOF);
    printf("Ok\n");
    fflush(stdout);

    return 0;
}

最佳答案

您使用 %s 调用 scanf 的方式可能会溢出 x 缓冲区。您至少应该使用宽度修饰符修改 scanf。

#include <stdio.h>
#include <string.h>

int main()
{
    #define MAXSIZE 1024
    char x[MAXSIZE];
    int n;
    while(scanf("%1024s", x) != EOF)
    {
        printf("len:%d %s", strlen(x), x);
        fflush(stdout);
    }
    return 0;
}

对于您的其他程序也是如此。

您的程序被阻止的原因是您的第二个 a.out 程序正在循环执行另一个 scanf,而同时父程序正在尝试读取返回结果的响应。

关于子进程在协进程中读取后挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11149846/

相关文章:

c - 循环未按预期运行

php - 无法打开流 : Permission denied in/opt/lampp/htdocs

c - 使用共享内存(mmap)和信号量进行进程间通信

c - 将内核内存写入 ext2 block

c - 在 C 中递归地打印 Linux 中路径中的所有文件和文件夹

linux - Mariadb - Blob 数据导入仅适用于转储的同一数据库

python - 在 linux (Python) 中使用其名称终止进程

c++ - win32下如何设置RichEdit的回调机制

c++ - 如何测试输出到 std::cout(连接到管道)是否会阻塞

c - Unix shell : how do I check user input to see if it's a valid unix command?