2013-11-22 3 views
0

У меня проблема с дочерними процессами и трубами в C.Отправить двоичные данные по трубам C

Моя программа создает два дочерних процесса (silblings), а также две трубы. Отец читает от stdin и отправляет данные через первый канал. Первый ребенок перенаправляет stdin на первый канал и stdout на второй канал. После этого ребенок бежит gzip -cf с execlp(3). Второй ребенок читает со второго канала и записывает данные в stdout (или в файл).

Я пробовал, но он не работает с двоичными данными. Если первый ребенок отправляет только текстовые данные через второй канал (без использования gzip), а второй ребенок читает его, программа работает нормально. Но если я использую gzip с execlp(), и процесс записывает двоичные данные, программа не работает, потому что я не получаю все данные.

Вот часть кода:

Первый ребенок:

/* Close the pipe-ends which are not needed [...] */ 
/* Redirect the stdin and stdout with dup2 [...] */ 

if(execlp(EXEC,EXEC_ARG0,EXEC_ARG1,(char*) 0) == -1) /* run execlp with 'gzip -cf' */ 
    bail_out(EXIT_FAILURE,"Child_1: Cannot execute "EXEC_ARG0" "EXEC_ARG1"!"); 

Второй ребенок:

/* Close the pipe-ends which are not needed [...] */ 

FILE *fd = NULL; 
char str[4096]; 

fd = fdopen(pipefd_com2[0],"rb"); 
(void) fread(str,sizeof(str),1,fd); /* read from pipe */ 
(void) fclose(fd); 

FILE *fw = NULL; 

if(file_arg == NULL) /* check if there was a file as argument */ 
    fw = stdout; 
else 
    fw = fopen(file_arg,"wb"); 

if(fw == NULL) 
    bail_out(EXIT_FAILURE,"Failed to write file!"); /* does not return */ 

(void) fwrite(str,strlen(str),1,fw); /* write to stdout or file */ 
(void) fclose(fw); 
+1

Преднамеренное отбрасывание в пустоту в этом коде для шумоподавления непроверенных предупреждений о возвращаемом значении, независимо от того, какой статический анализ тщательно изучает ваш код, особенно неудобен, поскольку по крайней мере в одном случае ** не ** проверка этих значений является частью вашей проблемы , – WhozCraig

ответ

2

strlen функция для строк C-типа, а не для двоичных данных , Кроме того, ваши параметры до fread неверны. Второй параметр - размер каждого объекта Вы читаете. Для произвольных двоичных данных это должно быть 1, так как каждый объект является байтом. Это сделает возвращаемое значение от fread количеством прочитанных байтов, что вам нужно будет передать в fwrite в качестве третьего параметра.

В сумме:

size_t bytes_read; 
// ... 
bytes_read = fread(str,1,sizeof(str),fd); /* read from pipe */ 
// ... 
(void) fwrite(str,1,bytes_read,fw); /* write to stdout or file */ 

Вы должны также проверить возвращаемое значение fread.

+0

Спасибо большое! Оно работает. –

Смежные вопросы