2017-01-09 5 views
0

Я изучаю параметры процессов связи на C++. Началось с идеи связать трубу Unix с std :: cout, но я мог заставить ее работать. При записи напрямую с использованием записи (STDOUT_FILENO) я получаю ожидаемый результат. При записи с использованием std :: cout я получаю меньший и случайный вывод.Сопоставление UNIX Pipe с C++ std :: cout

#include <iostream> 
#include <unistd.h> 
#include <fcntl.h> 

const int PIPE_READ = 0; 
const int PIPE_WRITE = 1; 

int main() { 
    int pfd[2]; 

    if(pipe(pfd) == -1){ 
     std::cout << "Cannot create pipe" << std::endl; 
     return 0; 
    } 
    int pid = fork(); 
    if(pid == -1){ 
     std::cout << "Error on fork: " << errno << std::endl; 
    } else if(pid == 0) { // Child process 
     if(dup2(pfd[PIPE_WRITE],STDOUT_FILENO) < 0) { 
      std::cout << "Cannot redirect STDOUT: " << errno << std::endl; 
      return 0; 
     } 
     close(pfd[PIPE_WRITE]); 

     for(int i = 0; i < 8; i++){ 
      int data = i; 
      write(STDOUT_FILENO,&data,sizeof(int)); // Works 
      //std::cout << data; // Don't work 
     } 
    } else { // Parent process 
     close(pfd[PIPE_WRITE]); 
     for(int i = 0; i < 8; i++){ 
      int data; 
      ssize_t status; 
      if((status = read(pfd[PIPE_READ],&data,sizeof(int))) != sizeof(int)) { 
       std::cout << "Error (" << errno << ") on read: " << status << std::endl; 
       return -1; 
      } 
      std::cout << data << std::endl; 
     } 
    } 
    return 0; 
} 

ответ

1

Давайте внимательнее посмотрим на ваши письма:

write(STDOUT_FILENO,&data,sizeof(int)); // Works 
//std::cout << data; // Don't work 

Первый «работает» версия записать содержимое data в сыром виде двоичного кода на стандартный вывод. Во второй «нерабочей» версии введите значение dataкак текст до стандартного выхода.

Если значение data является 5 то write вызов будет написать целое значение 5 в то время как std::cout << data будет написать целое значение 53 (с использованием ASCII encoding).

Это, конечно, имеет значение, когда вы читаете данные как исходные и двоичные int в родительском.

Если вы хотите записать необработанные двоичные данные в std::cout вы должны использовать std::ostream::write:

std::cout.write(reinterpret_cast<char*>(&data), sizeof data); 

выше линии эквивалентно write системного вызова у вас есть.


Также важно знать, что написание int в сыром виде запишет sizeof(int) байт, как правило, четыре. Написание однозначного целого числа в виде текста будет писать один байт.

Ваша петля будет писать восемь чисел, что означает, что она будет писать 32 байта (4 * 8) при использовании write. Если вы выведете с использованием << в std::cout, тогда вы напишете 8 байтов. Когда вы прочтете, вы прочтете эти 8 байтов и поместите в два одиночных значения int, тогда звонок read вернет 0, потому что труба была закрыта.

Что значения этих двух значений int будут зависеть от вашей архитектуры оборудования, если это little-endian or big-endian.

+0

Маленькая ошибка :). Мое предположение заключалось в том, что cout может выводить как строковые, так и двоичные данные в зависимости от типа данных. Еще одно: изменение файловых дескрипторов не было отражено в объекте std :: cout C++. Благодарю. – Zayl

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