我需要用3个过程创建程序:
第一个进程应重复读取/dev/urandom,并通过管道将每个周期15个字符发送到第二个进程。
第二个进程应将接收到的数据转换为十六进制,并通过fifo将结果发送到第三个进程。
第三个过程应该打印接收到的数据。
这就是我到目前为止写的。使用管道进行通信工作正常,但是fifo有一些问题-当我将n更改为更大的数字(如100000或1000000)时,程序不会启动。当它变小,比如500或1000,程序就工作了。这背后的原因可能是什么?
这就是我运行它的方式:

cat /dev/urandom | ./a.out

下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#define FIFO "my_fifo"

int main(void) {
    int pdesk[2];
    char buf[15];
    char buffer[15];
    char hex[30];
    char f[30];
    int len;
    int n;

    n = 100;

    umask(0);
    mkfifo(FIFO, 0666);

    pipe(pdesk);

    if (fork() == 0) {
        for (int i = 0; i < n; i++) {
            read(STDIN_FILENO, buffer, 15);
            write(pdesk[1], buffer, 15);
        }
        close(pdesk[1]);
    } else {
        sleep(1);
        int fp;

        for(int i = 0; i < n; i++) {
            read(pdesk[0], buf, 15);

            for(int a = 0, b = 0; b < 30; ++a, b+= 2)
                sprintf(hex + b, "%02x", buf[a] & 0xff);

            fp = open(FIFO, O_WRONLY);
            write(fp, hex, 30);
            close(fp);
            usleep(10000);
        }
        close(pdesk[0]);
    }

    if (fork() == 0) {
        sleep(2);
        int fp;

        for (int i = 0; i < n; i++) {
            fp = open(FIFO, O_RDONLY);
            read(fp, f, 30);
            printf("Odczytano: %s\n", f);
            close(fp);
            usleep(10000);
        }
    }
}

最佳答案

如果我正确理解您的代码,它将执行以下操作:
使用第一个fork启动一个从stdin读取并写入管道的子对象。
您的父进程从管道读取并写入FIFO。
当父进程完成循环时,它调用第二个fork来创建另一个子进程,该子进程将从FIFO读取并打印数据。
当循环计数太大时,您将达到FIFO的缓冲区限制,父进程将阻塞,因为没有进程从FIFO读取。当进程以写入FIFO的方式被阻止时,它将永远不会创建期望从FIFO读取的子进程。
我认为主要的问题是,在开始从管道读取数据并写入FIFO的循环之前,应该创建第二个子循环。
一些附加说明:
使用cat /dev/urandom | ./a.out程序不会直接读取/dev/urandom。它从一个可能有不同行为的管道读取数据。
您应该始终检查read的返回值。它会告诉你它读了多少字节,可能比你要求的要少。如果你想要15个字符,如果少于15个字符,你可能要读几遍。
这同样适用于write

关于c - 流程之间的通信-管道和FIFO,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53870872/

10-15 01:07