Связь между процессами - pipe и fifo
Мне нужно создать программу с 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);
}
}
}
2 ответа
Если я правильно понимаю ваш код, он сделает следующее:
С первым fork
вы запускаете ребенка, который читает из стандартного ввода и пишет в канал.
Ваш родительский процесс читает из канала и пишет в FIFO.
Когда ваш родительский процесс завершил свой цикл, он вызывает второй fork
создать другого потомка, который будет читать из FIFO и распечатывать данные.
Когда число циклов слишком велико, вы достигнете предела буфера FIFO, и родительский блок заблокируется, потому что ни один процесс не читает из FIFO. Когда процесс блокируется при записи в FIFO, он никогда не создаст дочерний элемент, который, как ожидается, будет читать из FIFO.
Я думаю, что основная проблема заключается в том, что вы должны создать второго потомка перед началом цикла, который читает данные из канала и записывает данные в FIFO.
Некоторые дополнительные замечания:
С cat /dev/urandom | ./a.out
ваша программа не читает /dev/urandom
непосредственно. Он читает из канала, который может вести себя по-другому.
Вы должны всегда проверять возвращаемое значение read
, Он скажет вам, сколько байтов он прочитал, что может быть меньше, чем вы просили его прочитать. Если вы хотите иметь ровно 15 символов, вам может потребоваться прочитать несколько раз, если вы получите менее 15 символов. То же самое относится и к write
,
Большое спасибо. Когда процесс, который отображает данные, находится над другими дочерними процессами, он, наконец, работает.
С котом / 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, независимо от того, что я называю. Есть ли способ проверить это?