Неблокирующий FIFO: определить, существует ли читатель?

Я создал FIFO, в который я могу выполнять неблокирующие записи следующим образом:

// others, searching for a non-blocking FIFO-writer may copy this ;-)
mkfifo("/tmp/myfifo", S_IRWXU);
int fifo_fd = open("/tmp/myfifo", O_RDWR);
fcntl(fifo_fd, F_SETFL, fcntl(fifo_fd, F_GETFL) | O_NONBLOCK);

// and then in a loop:
LOGI("Writing into fifo.");
if (write(fifo_fd, data, count) < 0) {
    LOGE("Failed to write into fifo: %s", strerror(errno));
}

Неблокирующая запись работает идеально.

С другой стороны, я открываю FIFO для чтения и выполняю ту же функцию fcntl(), чтобы сделать чтение() неблокирующим.

Теперь я хотел бы сделать несколько вычислений (нагружающих ЦП) на стороне записи, но ТОЛЬКО при наличии подключенного ридера.

Поэтому мне нужно найти способ на стороне записи, чтобы определить, открыт ли FIFO для чтения где-то еще.

Кто-нибудь знает, как этого добиться?


person Martin L.    schedule 28.01.2013    source источник
comment
В вашем заголовке написано "писатель", в вашем вопросе написано "читатель"...   -  person Oliver Charlesworth    schedule 28.01.2013
comment
@Oli .. И код говорит O_RDWR (кстати, это не POSIX)   -  person Anton Kovalenko    schedule 28.01.2013
comment
› В вашем заголовке написано «писатель».. о да, спасибо.   -  person Martin L.    schedule 28.01.2013
comment
Почему бы не сделать open("fifo", O_WRONLY | O_NONBLOCK)? Это не удастся с ENXIO, если нет читателей.   -  person melpomene    schedule 28.01.2013
comment
Потому что процесс записи должен быть абсолютно независим от ридера, но ридер должен быть подключаемым во все моменты (читатель понимается как необязательный монитор). Тогда это будет возможно только в том случае, если я выполню open() и close() в цикле записи. Насколько (не)эффективно это будет? Может быть, это менее вредно, чем я думал?   -  person Martin L.    schedule 28.01.2013
comment
Ну попробуй померь. Самое главное, что читатель может появиться в любой момент, после того, как вы проверите и обнаружите, что читателей нет. Может ли читатель заблокировать один раз, даже если писатель мог бы накормить его, если бы он знал, что должен?   -  person Anton Kovalenko    schedule 28.01.2013
comment
Я сейчас попробовал это - кажется, нет проблем с производительностью. НО: поскольку я делаю открытие и закрытие в цикле, смоделированный читатель cat /tmp/myfifo закрывается сразу после 1 кругового обхода (писатель закрывается -> cat думает, что все готово). Грустно, кажется, это не правильный путь.   -  person Martin L.    schedule 28.01.2013


Ответы (1)


Теперь я хотел бы сделать несколько вычислений (нагружающих ЦП) на стороне записи, но ТОЛЬКО при наличии подключенного ридера.

Для этого вы можете просто создать сокет и, когда потребитель подключится к нему, выполнить некоторую работу и написать ответ.
Но я думаю, что лучшим решением будет подготовить результаты вычислений для потребителей до того, как они подключатся (или открыть FIFO). но вы не хотите, чтобы производитель работал, если работа не потребляется. Итак, определите N — количество результатов работы, которое вы готовы оставить для потребления, и позвольте производителю (или производителям) работать и сохранять результаты в очереди размера N до тех пор, пока она не заполнится.
Вы можете реализовать это с помощью потоков, один поток прослушивает соединения, извлекается из очереди и записывает в потребитель, а один или несколько потоков-производителей работают и отправляют в очередь.
Или вы можете использовать очереди сообщений POSIX, чтобы избежать проблем с многопоточностью. Создайте очередь размером N, независимые производители (несколько процессов, написанных на разных языках) могут помещать в очередь до тех пор, пока она не заполнится, и несколько независимых потребителей выйдут из нее.

person bahaa    schedule 29.01.2013
comment
Спасибо за ваш ответ. Очереди сообщений POSIX действительно интересны. Но теперь мое решение заключалось в том, что клиент создает небольшой контрольный файл, который проверяется рабочим через доступ (..). Расчет производится только в том случае, если существует хотя бы один управляющий файл. - person Martin L.; 30.01.2013