2011-01-19 5 views
0

У меня есть случай, когда у меня есть входящий поток сложных сообщений, которым требуется некоторая обработка, прежде чем они будут переданы в упрощенном формате фактическому обработчику.Контроль готовности файловых дескрипторов

Я хотел бы использовать дескриптор файла FIFO, с одним потоком, заполняющим его с одного конца, а другой - чтением другого. Теперь вид поведения, который я хотел бы иметь: поток чтения ждет с select(), и я хотел бы гарантировать, что после пробуждения есть полный пакет, который можно прочитать с вызовом read(), т.е. я хочу избежать для сборки пакетов из-за фрагментации из-за размеров буфера (пакеты гарантированно будут ниже предела прохождения буфера ядра к пользователю).

Я хочу знать, есть ли способ настроить FIFO таким образом, чтобы я мог вручную определить, когда дескриптор файла готов, то есть когда производитель успешно написал полный пакет, я хотел бы иметь способ подачи сигнала на конец считывания (через дескриптор файла), что чтение готово. Есть ли способ достичь этого через ioctl() или есть какая-то абстракция, кроме FIFO, которая предлагает такое поведение (в мире Linux)? (Я знаю о pthread и переменных условиях, но я хотел бы связь между производителем и потребителем должен быть ограничен общим файловым дескриптор.)

ответ

1

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

Нет такого способа.

Вы должны.

  • Определить какое-то изображение в обрамлении. например добавьте длину сообщения в сообщение или разделите их на новую строку (если в сообщении не может появиться новая строка). В случае сообщений, разделенных новой строкой, вы можете обернуть файл filedescriptor в FILE * и fgets(), если вы не зависите от select() для мультиплексирования нескольких потоков или предоставления тайм-аута.
  • Будьте готовы обрабатывать read() или аналогичные читать 1 сообщение, менее 1 сообщения или более 1 сообщения - fifo - это просто поток байтов, поэтому на этом слое нет границ сообщений.
  • Разберите сообщения, которые вы прочитали, в соответствии с тем, как вы решили их разделить.

Другая альтернатива - всегда отправлять сообщение с фиксированной длиной, чтобы вы всегда знали, сколько нужно прочитать, чтобы получить 1 сообщение или, возможно, использовать сокеты-пакеты AF_UNIX - до тех пор, пока вы можете определить разумный максимальный размер сообщение.

2

Попробуйте socketpair() вместо pipe()/mknod(S_IFIFO).

Сокета пара может быть сделан в области AF_UNIX с типом SOCK_STREAM (поток на основе, ваше использование будет необходимо кадрирование/разборка), SOCK_DGRAM (дейтаграммы на основе, не будут фрагментированы или объединен), или SOCK_SEQPACKET (запись на основе , могут быть фрагментированы, но не объединены).

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