2016-12-17 1 views
0

При использовании FIFO в одном процессе, похоже, что после того, как оба конца были открыты, а затем закрыты, повторное использование FIFO невозможно. Любая попытка открыть закрытый конец завершается неудачей или дескриптор возвращенного файла бесполезен.Невозможно повторно открыть FIFO, когда тот же процесс использует оба конца FIFO

Возможно ли обойти это поведение, или мы должны держать оба конца FIFO открытым до тех пор, пока мы не будем абсолютно уверены, что нам это больше не нужно?

Вот некоторые тестового кода, который показывает и попытка возобновить закрытый конец записи в виде FIFO:

#include <iostream> 
#include <cstdio> 
#include <errno.h> 
#include <fcntl.h> 
#include <limits.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

using namespace std; 

int main(int argc, const char **argv) 
{ 
     cout << "Creating an instance of a named pipe..." << endl; 
     mode_t prevMask = umask(0); 
     if (mknod("my_pipe", S_IFIFO | 0666, 0)) 
     return -1; 
     umask(prevMask); 

     cout << "Opening Read end..." << endl; 
     int fdM = open("my_pipe", O_RDONLY | O_NONBLOCK); 
     if (fdM == -1) 
     return -1; 

     cout << "Opening Write end..." << endl; 
     int fdS = open("my_pipe", O_WRONLY | O_NONBLOCK); 
     if (fdS == -1) 
     return -1; 

     cout << "Sending data to pipe..." << endl; 
     const char *data = "Hello my friend!"; 
     ssize_t NbOfBytesWritten = write(fdS, data, strlen(data)); 
     if (NbOfBytesWritten < 0) 
     return -1; 
     cout << "Number of bytes sent: " << NbOfBytesWritten << endl; 

     cout << "Closing Write end..." << endl; 
     if (close(fdS)) 
     return -1; 

     cout << "Reopening Write end..." << endl; 
     fdS = open("my_pipe", O_WRONLY | O_NONBLOCK); 
     if (fdS == -1) 
     { 
     cout << "open() - failed("<< errno << "): " << strerror(errno) << '.'; 
     remove("my_pipe"); 
     return -1; 
     } 

     cout << "Sending some more data to pipe..." << endl; 
     data = "What's up?"; 
     NbOfBytesWritten = write(fdS, data, strlen(data)); 
     if (NbOfBytesWritten < 0) 
     return -1; 
     cout << "Number of bytes sent: " << NbOfBytesWritten << endl; 

     cout << "Reading data from pipe..." << endl; 
     char buff[128]; 
     ssize_t numBytesRead = read(fdM, buff, 127); 
     if (NbOfBytesWritten < 0) 
     return -1; 
     buff[numBytesRead] = '\0'; // null terminate the string 
     cout << "Number of bytes read: " << numBytesRead << endl; 
     cout << "Message: " << buff << endl; 

     cout << "Closing Write end..." << endl; 
     if (close(fdS)) 
     return -1; 

     cout << "Closing Read end..." << endl; 
     if (close(fdM)) 
     return -1; 

     cout << "Deleting pipe..." << endl; 
     if (remove("my_pipe")) 
     return -1; 

    return 0; 
} 

Здесь выход:

Creating an instance of a named pipe... 
Opening Read end... 
Opening Write end... 
Sending data to pipe... 
Number of bytes sent: 16 
Closing Write end... 
Reopening Write end... 
open() - failed(6): No such device or address. 

Я также испытал подобный код пытается возобновить закрытый конец чтения (в то время как конец записи был открыт). В этом случае функция open() будет успешной, но функция read(), использующая дескриптор файла, возвращенный функцией open(), завершится с ошибкой: Ошибка связи при отправке. (70)

EDIT:

Я использую CYGWIN.

+0

Это работает без ошибок на моем Linux. – PSkocik

+0

Вам нужно, чтобы оба конца были открыты. Когда все концы записи закрыты, читатель получает EOF. И когда все прочитанные концы закрыты, писатель получает «EPIPE», если они пытаются писать. – Barmar

+0

@Barmar - Вопрос в том, что «Почему невозможно возобновить конец FIFO?» Речь идет не о том, как писать или читать с FIFO, который не связан с обоих концов. – Guett31

ответ

1

В коде Linux отлично работает. Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что именованные каналы на CYGWIN не работают очень хорошо и не могут следовать семантике POSIX. См. FIFO (named pipe) is broken on Cygwin. Вероятно, у вас такая же проблема.

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