2015-12-08 2 views
1

У меня есть труба, обеспечивающая связь между двумя процессами в разветвленной программе. Он был создан с помощью вызова pipe() - http://linux.die.net/man/2/pipe . Все идет правильно, пока я не хочу выполнять некоторые операции с файлами.Операции с вилками, трубами и файлами

Этот код работает:

pipe.writeBuffer(message.c_str(), message.length()); 
ofstream file; 
file.open(name.c_str(), ios::app); 
file << "stringData"; // put some data to file (many times) 

Но это не:

ofstream file; 
file.open(name.c_str(), ios::app); 
pipe.writeBuffer(message.c_str(), message.length()); 
file << "stringData"; // put some data to file (many times) 

Во втором примере нет никакого эффекта "файл < < someStream" - я получаю пустой файл. Что не так с этим? Это проблема с файловым дескриптором? Труба использует fd [0] - вход и fd [1] - выход. Может быть, fstream использует также тот же обработчик выходного файла?

Здесь «работает» образец: http://pastebin.com/gJ4PbHvy

#include <sys/types.h> 
#include <cstdlib> 
#include <unistd.h> 
#include <iostream> 
#include <fstream> 

#define maxSize 64 

using namespace std; 

class Pipe 
{ 
    public: 
     Pipe() 
     { 
      pipe(fdesc); 
     } 

     ~Pipe() {} 

     void writeBuffer(const char* message, size_t length) 
     { 
      close(fdesc[0]); 
      write(fdesc[1], message, length); 

     } 

     void readBuffer() 
     { 
      char buffer[maxSize]; 
      close(fdesc[1]); 
      size_t result = read(fdesc[0], &buffer, sizeof(buffer)); 
      cout << buffer << endl; 

     } 

    private: 
     int fdesc[2]; 

}; 

class Writer 
{ 
    public: 
     Writer(Pipe &obj) 
     { 
      pipe = obj; 
     } 

     ~Writer() 
     {} 

     void entry() 
     { 
      std::string name = "./myFile"; 
      ofstream file; 
      file.open(name.c_str(), ios::app); 

      std::string message = "hello world"; 
      pipe.writeBuffer(message.c_str(), message.length()+1); 

      if (file.is_open()) 
      { 
       file << "Hello World!" << endl; 
       file.close(); 
      } 
      else 
      { 
       perror("file.is_open()"); 
      } 

      sleep(1); 

     } 

    private: 
     Pipe pipe; 

}; 


class Reader 
{ 
    public: 
     Reader(Pipe &obj) 
     { 
      pipe = obj; 
     } 

     ~Reader() 
     {} 


     void entry() 
     { 
      pipe.readBuffer(); 
      sleep(1); 

     } 

    private: 
     Pipe pipe; 

}; 

int main(int argc, char *argv[]) 
{ 
    Pipe pipe; 
    Reader reader(pipe); 
    Writer writer(pipe); 

    pid_t pid = fork(); 

    if (pid == -1) 
    { 
     perror("fork"); 
     exit(EXIT_FAILURE); 
    } 

    if (pid == 0) 
    {  
     // child process 
     while(1) 
      reader.entry(); 

    } 
    else 
    { 
     // parent process 
     while(1) 
      writer.entry(); 

    } 

} 
+1

что somestream? Что такое сообщение? вопрос не имеет никакого смысла. – SergeyA

+0

Вы можете рассмотреть это: файл << "anything"; и во втором примере вы не найдете «ничего» в созданном файле. Первый образец работает так, как ожидалось. – neutrino

+0

Что такое 'ios :: app'? Вы проверяете, что файл был успешно открыт? Вы уверены, что файл закрыт, прежде чем проверять контекст файла? Между трубой и потоком, который вы используете, не может быть никакой связи. – SergeyA

ответ

1

С публикуемых программами, описанная проблема получения пустого файла не воспроизводима, так как на каждый запуске он делает написать одну строку Hello World! в myFile, но это все еще показывает ошибку, потому что вы намереваетесь писать одну строку каждую секунду. Причина в том, что close(fdesc[0]) в writeBuffer(): Хотя правильно закрыть конец считывания трубы один раз в процессе записи, это некорректно делать это каждый раз, когда вызывается writeBuffer(), поскольку этот файловый дескриптор может (и в случае под рукой, делает) были повторно использованы после первого close() для другого файла (здесь файл ofstream file), который после него закрывается вместо (уже закрытого) канала, так что в файл ничего не записывается. Fix: Устройте свою программу, чтобы закрыть конец трубы только один раз, e. г. путем изменения

  close(fdesc[0]); 

в

  if (0 <= fdesc[0]) close(fdesc[0]), fdesc[0] = -1; 
Смежные вопросы