C ++ Linux именованный канал висит на open () с O_WRONLY

Это мой простой код, который открывает именованный канал, записывает в него строку, а затем закрывает канал. Канал создается в другой функции, как указано ниже.

char * ipcnm = "./jobqueue";

std::cout << "opening job queue" << std::endl;

//ensure the jobqueue is opened
if ((jobq = open(ipcnm, O_WRONLY)) < 0) {
perror("open");
exit(-1);
}

std::cout << "queue opened" << std::endl;

// record the number of bytes written to the queue
size_t written = write(jobq, ptr, size*nmemb);

// close fifo
if (close(jobq) < 0) {
perror("close");
exit(-1);
}

// need to report to other agents the size of the job that was written
jobSizes.push_back(written);

но вызов open () зависает. Я убедился, что во время вызова нет никакого другого процесса, использующего fifo «jobqueue», и права доступа к файлу для очереди после ее создания устанавливаются prwxrwxr-x (я просто использую mkfifo(ipcnm, 0777) создать трубу.

Сначала я подумал, что это проблема этой группы o пропал, отсутствует w разрешения для этого канала, поэтому я вручную изменил их с помощью chmod, и он все еще зависает, так как «очередь открыта» никогда не печатается. Также не появляется сообщение об ошибке для perror («open»);

Что мне не хватает?

3

Решение

Когда вы открываете FIFO для записи, писатель блокируется, пока не будет считыватель.

Вы, вероятно, скучаете по читателю.

Вы не можете написать в канал, затем закрыть его, а затем попросить читателя прийти позже. Такая семантика хранения достигается с помощью обычного файла.

Трубы являются механизмом межпроцессного взаимодействия; канал, созданный открытием FIFO, похож на объект, возвращаемый pipe Функция библиотеки POSIX C, за исключением того, что pipe возвращает объект, который уже подготовлен для ввода / вывода, поскольку существует два дескриптора: противоположные концы открыты для противоположных направлений ввода / вывода. Принимая во внимание, что конечные точки FIFO открываются отдельно по одному.

Объект FIFO в файловой системе является лишь точкой контакта, которая позволяет нескольким процессам присоединяться к одному каналу.

Изначально не существует ни одного объекта трубы. Когда первый процесс выполняет open на объекте FIFO в файловой системе создается канал. Любые дополнительные open запросы от того же процесса или другого присоединения к тому же объекту pipe, хранящемуся в ядре. Ввод / вывод не может быть выполнен до тех пор, пока канал не будет открыт хотя бы один раз для чтения и хотя бы один раз для записи. Фактический канал ввода / вывода проходит через ядро; он не хранится в файловой системе. Когда все процессы закрывают трубу, объект уходит.

FIFO может быть спроектирован так, чтобы ввод / вывод мог начаться до того, как какой-либо процесс открыл объект для чтения. То есть, запрос на запись может быть разрешен для продолжения, а затем заблокирован только после заполнения канала. У этого дизайна были бы проблемы. Например, что если запись мала, чтобы канал не заполнялся? Автор запишет данные и продолжит их выполнение. Если он просто выходит до того, как читатель прочитает данные, данные исчезнут навсегда! Поведение блокировки гарантирует, что читатель будет там, чтобы поймать данные; когда блок записи разблокирован, он может быть уверен, что у считывателя открыт канал, и поэтому он может безопасно закрыть свой конец канала без потери данных. Проект, который не блокирует записи, даже когда нет доступного считывателя, должен был бы держать объект канала внутри ядра, даже когда ни у какого процесса его нет, чтобы писатель мог открыть канал, поместить в него данные, а затем уйти, и позже читатель может забрать данные. Иначе дизайн должен был бы обеспечить писателю close (аналогично SO_LINGER-настроенное поведение на сокете), который ожидает удаления ранее записанных данных.

12

Другие решения

Используйте O_RDWR вместо O_WRONLY для открытия. Это откроет fifo без блокировки, даже если читатель еще не открыт другим концом.

2

По вопросам рекламы [email protected]