简体   繁体   中英

Communication between processes - pipe and fifo

I need to create program with 3 processes:

  1. The first process should repeatedly read /dev/urandom and send 15 chars each cycle to the second process via a pipe .
  2. The second process should convert received data to hex and send the result to the third process via a fifo .
  3. The third process should print the received data.

This is what I wrote so far. Communication using the pipe is working fine, however there is some problem with the fifo - when I change n to a larger number such as 100000 or 1000000, the program doesn't start. When it's smaller, say 500 or 1000, the program works. What could be the reason behind that?

This is how I run it:

 cat /dev/urandom | ./a.out 

And here is the code:

#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);
        }
    }    
}

If I understand your code correct, it will do the following:

With the first fork you start a child that reads from stdin and writes to the pipe.

Your parent process reads from the pipe and writes to the FIFO.

When your parent process has finished its loop it calls the second fork to create another child which will read from the FIFO and print the data.

When the loop count is too large you will reach the buffer limit of the FIFO and the parent will block because no process is reading from the FIFO. When the process is blocked in writing to the FIFO it will never create the child that is expected to read from the FIFO.

I think the main problem is that you should create the second child before starting the loop that reads the data from the pipe and writes to the FIFO.

Some additional remarks:

With cat /dev/urandom | ./a.out cat /dev/urandom | ./a.out your program does not read /dev/urandom directly. It reads from a pipe which might behave differently.

You should always check the return value of read . It will tell you how many bytes it has read which may be less than you asked it to read. If you want to have exactly 15 characters you might have to read several times if you get less than 15 characters. The same applies to write .

Thank you very much. When the process that displays data is above other child processes, it finally works.

With cat /dev/urandom | ./a.out your program does not read /dev/urandom directly. It reads from a pipe which might behave differently.

How could I change it?

The programs also needs to read files the same way it reads from /dev/urandom, for example:

cat file.txt | ./a.out

I took your advice and started to check the value of read and now it doesn't go behind the range of file. The problem is I don't know how to check which parameter was called (and hence I can't check the length of file) - if it was file.txt, /dev/urandom, none or anything else. I tried with

int main(char argc, char* argv[])

but argv is always ./a.out, no matter what I call. Is there any way to check that?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM