Поскольку кажется, что вы намереваетесь выполнить одно чтение всех данных из конвейера, я думаю, что следующее поможет вам лучше, чем методы разделителя + кодирования или мини-заголовка, предложенные в других ответах:
Из трубы (7) manpage:
Если все файловые дескрипторы ссылаются на
конец записи трубы был
закрыто, то попытка чтения (2)
из трубы увидим конец файла
(чтение (2) вернет 0).
Следующий пример был взят из man-страницы pipe (2) и перевернут так, что дочерний элемент пишет, родительский читает (просто чтобы убедиться). Я также добавил буфер переменного размера. Ребенок будет спать 5 секунд. Задержка гарантирует, что exit () дочернего элемента не может иметь ничего общего с pipeio (родительский файл напечатает полную строку перед выходом дочернего элемента).
#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char *
slurpfd(int fd)
{
const int bytes_at_a_time = 2;
char *read_buffer = NULL;
int buffer_size = 0;
int buffer_offset = 0;
int chars_io;
while (1) {
if (buffer_offset + bytes_at_a_time > buffer_size) {
buffer_size = bytes_at_a_time + buffer_size * 2;
read_buffer = realloc(read_buffer, buffer_size);
if (!read_buffer) {
perror("memory");
exit(EXIT_FAILURE);
}
}
chars_io = read(fd,
read_buffer + buffer_offset,
bytes_at_a_time);
if (chars_io <= 0) break;
buffer_offset += chars_io;
}
if (chars_io < 0) {
perror("read");
exit(EXIT_FAILURE);
}
return read_buffer; /* caller gets to free it */
}
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
assert(argc == 2);
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]) + 1);
close(pipefd[1]); /* Reader will see EOF */
/* sleep before exit to make sure that there
will be a delay after the parent prints it's
output */
sleep(5);
exit(EXIT_SUCCESS);
} else { /* Parent reads from pipe */
close(pipefd[1]); /* Close unused write end */
puts(slurpfd(pipefd[0]));
close(pipefd[0]);
wait(NULL); /* Wait for child */
_exit(EXIT_SUCCESS);
}
}
Из вашего комментария теперь я вижу, что вы можете читать данные по мере их поступления, обновлять пользовательский интерфейс или что-то еще, чтобы отражать состояние вашей системы. Для этого откройте канал в неблокирующем (O_NONBLOCK) режиме. Прочитайте многократно все, что доступно, пока -1 не вернется и не ошибется == EAGAIN, и выполните анализ. Повторите unil read возвращает 0, что указывает на то, что дочерний элемент закрыл канал.
Чтобы использовать буфер в памяти для функций File *, вы можете использовать fmemopen () в библиотеке GNU C.