2013-11-19 2 views
3

Я разрабатываю программу C в Linux, где у меня будет два потока. Один основной поток - event_processor_thread, который выполняет основную обработку функции. Второй поток - поток event_dispatcher, всегда работающий в фоновом режиме, запись и считывание с нескольких интерфейсов в реальном времени (без блокировки async i/o)Зачем использовать writefds в select? Как их использовать на практике?

Я провел некоторое исследование в сети и нашел, что лучшие способы реализации неблокирующая разъем ввода/вывода может быть достигнуто с помощью

  1. libevent
  2. select()

Я выбрал последнее, так как его легче, и я буду иметь на границах наиболее 4 считываемых из/сог это к.

Понятно, что механизмы прослушивания/чтения используются с использованием readfds, но я не уверен, как использовать writefds! Если я поместил свои данные из event_processor_thread в разделяемую память и попросил этот поток диспетчера событий прочитать это из разделяемой памяти и написать с помощью send(), выберете сами позаботиться о передаче данных в сокет? Вот почему мне нужно использовать writefds в select()?

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

+0

Как бы вы реализовали базовый цикл событий? http://stackoverflow.com/questions/658403/how-would-you-implement-a-basic-event-loop – HAL

+0

Обратите внимание, что подход libevent более переносим на разные платформы. – Ztyx

ответ

1

Нет, select() не будет «заботиться о письме». Он уведомит вас, когда один или несколько дескрипторов файлов, включенных в набор writefds, станут доступными для записи. Это может означать, что рассматриваемые fd (s) завершили предыдущую (неблокирующую) запись, которую вы сделали, чтобы теперь вы могли сделать другую.

+0

Спасибо, и @Klas Lindback, вы хотите сказать, что я должен реализовать что-то вроде этого: 1. написать в сокет 2. Если количество записанных байтов не заполнено, вернитесь как можно скорее, 3. select() отправит уведомление, если сокет готов к записи 4. Запишите оставшиеся данные в сокет – vinit

+0

@vinit: Да, это один из вариантов использования параметра 'writefds'' select() '(хотя вы не останавливаетесь, когда количество записанных байтов «не полный», вы останавливаетесь, когда 'send()'/'write()' говорит вам прекратить, потому что возникает ошибка EAGAIN или EWOULDBLOCK'. Другой вариант использования - обнаружить, когда неблокирующее 'connect()' успешно. –

10

Запись в формате write - это проверка того, что дескриптор файла готов для записи. Для сокета это означает, что буфер отправки, связанный с сокетом, не заполнен.

Предположим, что сокеты на вашей платформе имеют буфер 8 килобайт и вы хотите отправить 100 килобайт данных.

Вы вызываете write и получаете возвращаемое значение 8192, указывающее, что записаны первые 8192 байта. Следующий вызов для записи возвращает либо EAGAIN, либо EWOULDBLOCK, указывающий, что буфер отправки заполнен.

Теперь вы можете использовать select, чтобы узнать, когда снова есть место в буфере отправки (т. Е. Когда один клиент tcp/ip был передан клиенту), чтобы вы могли продолжать писать. В то же время вы можете слушать новые подключения и ждать ввода от клиентов.

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

0

select() сообщает вам, когда файловый дескриптор доступен для записи. Для сокета это означает, что он может принимать новые исходящие данные без блокировки вызывающего. Если вы вызываете send() или write(), а исходящий буфер сокета заполнен, вы получите ошибку EAGAIN или EWOULDBLOCK, после чего вы прекратите запись в этот сокет до тех пор, пока он не станет перезапущен.select() также может сообщить вам, когда сокет станет доступен для записи после вызова неблокирующего connect(), что указывает на успешное соединение, и данные могут начать записываться в одноранговую сеть.

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