Связь между процессами - pipe и fifo - PullRequest
0 голосов
/ 20 декабря 2018

Мне нужно создать программу с 3 процессами:

  1. Первый процесс должен многократно читать /dev/urandom и отправлять 15 символов каждый цикл во второй процесс по трубе .
  2. Второй процесс должен преобразовать полученные данные в шестнадцатеричный формат и отправить результат третьему процессу через fifo .
  3. Третий процесс должен распечатать полученные данные.

Это то, что я написал до сих пор.Связь с использованием канала работает нормально, однако с 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);
        }
    }    
}

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Большое спасибо.Когда процесс, который отображает данные, находится над другими дочерними процессами, он, наконец, работает.

С котом / dev / urandom |./a.out ваша программа не читает / dev / urandom напрямую.Он читает из канала, который может вести себя по-разному.

Как я могу это изменить?

Программы также должны читать файлы так же, как это читает из / dev / urandom, дляпример:

cat file.txt | ./a.out

Я воспользовался вашим советом и начал проверять значение прочитанного, и теперь оно не выходит за пределы диапазона файла.Проблема в том, что я не знаю, как проверить, какой параметр был вызван (и, следовательно, я не могу проверить длину файла) - если это был file.txt, / dev / urandom, none или что-либо еще.Я пытался с

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

, но argv всегда ./a.out, независимо от того, что я называю.Есть ли способ проверить это?

0 голосов
/ 20 декабря 2018

Если я правильно понимаю ваш код, он сделает следующее:

С первым fork вы запустите ребенка, который читает из stdin и пишет в канал.

Ваш родительПроцесс читает из канала и записывает в FIFO.

Когда ваш родительский процесс завершил свой цикл, он вызывает второй fork, чтобы создать другого дочернего элемента, который будет читать из FIFO и печатать данные.

Когда количество циклов слишком велико, вы достигнете предела буфера FIFO, и родительский блок заблокируется, потому что ни один процесс не читает из FIFO.Когда процесс блокируется при записи в FIFO, он никогда не создаст дочерний элемент, который, как ожидается, будет читать из FIFO.

Я думаю, что основная проблема заключается в том, что вы должны создать второго дочернего элемента до запуска цикла, который читаетданные из канала и записываются в FIFO.

Некоторые дополнительные замечания:

При cat /dev/urandom | ./a.out ваша программа не читает /dev/urandom напрямую.Он читает из канала, который может вести себя по-другому.

Вы всегда должны проверять возвращаемое значение read.Он скажет вам, сколько байтов он прочитал, что может быть меньше, чем вы просили его прочитать.Если вы хотите иметь ровно 15 символов, вам может потребоваться прочитать несколько раз, если вы получите менее 15 символов.То же относится и к write.

...