#c #pipes #fifo
Допустим у нас есть именованный канал. Мы его открыли на чтение и читаем читаем читаем. Но вдруг писатель удалил этот pipe(ошибка или ещё что-то). Как правильно проверить что pipe больше не существует. Корректно ли проверять результат read и если он равен 0, то считать что канал отвалился? Если нет данных, то read будет долго ждать своего часа. Но read возвращает ноль если достигнут конец файла (а pipe по сути тот же файл, ну почти. поправьте если я ошибаюсь.) и это вовсе не значит что файл удален (для пайпов не уверена, поэтому и спрашиваю). Подскажите как правильно проверить, что pipe закрыт(удален).
Ответы
Ответ 1
При использованиие функции read() Если в канале нет данных будет возврашен 0 а если произошла ошибка будет возврашено значение -1 и в переемной errno установлен код ошибки. Ну тут еще важен момет как открыт канал. В блокируещем или не блокируещем режими. Но всеравно функция чтения не сможет указать что файл был удален. Поэтому если в программе есть вероятность что канал будет удален. То перед чтением из канала нужно воспользоваться функцией stat() она укажет существует такой файл или нет. И в этом случаи нужно открывать файл в неблокируешем режиме fd = open("test.pipe",O_RDONLY|O_NONBLOCK);Ответ 2
До тех пор пока хотя бы один процесс держит pipe открытой, объект не будет удалён. То есть даже если FIFO файл удалён (согласно stat()), read() всё равно может вернуть данные из уже открытой pipe. Если нет процессов, в которых pipe открыта для записи, то read() вернёт 0 (чтобы отметить EOF), если больше нет данных в буфере pipe. Если ваша задача прочитать данные из FIFO, то открывайте (open()) и читайте (read()), не забывая обрабатывать ошибки. Никакие дополнительные вызовы не нужны. Вот пример, который показывает, что можно данные писать и читать даже если stat() говорит что нет файла (исполняемый псевдо-код): #!/usr/bin/env python from os import * mkfifo('fifo') # create named pipe r, w = pipe() # "communication tube" between the parent and the child if fork(): # parent process (the reader) close(r) # close the unused end of the pipe fd = open('fifo', O_RDONLY) # open for reading write(1, read(fd, 512)) # read some remove('fifo') # delete fifo write(w, b'\0') # tell the child, the parent removed fifo close(w) # nothing more to say wait() # wait until the writer exits write(2, b'read some more\n') write(1, read(fd, 512)) # read some more if not read(fd, 512): write(1, b'EOF') # read() returns nothing else: # child: writer process close(w) # close the unused end of the pipe fd = open('fifo', O_WRONLY) # open for writing write(fd, b'data\n') read(r, 512) # wait until the parent removes fifo close(r) # won't listen no more try: # make sure fifo is gone stat('fifo') except IOError: pass else: assert 0, "shouldn't happen" write(fd, b'more data\n') # write after fifo is removed _exit(0) Если вас интересует узнать когда имя файла (fifo) было удалено (а не возможность чтения данных), то чтобы stat() не вызывать постоянно, можно сервисы такие как предложенный @avp inotify для Linux использовать (на разных системах—разные интерфейсы, но сама возможность на многих распространённых системах есть).
Комментариев нет:
Отправить комментарий