Системный вызов Select() в потоках?

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

Теперь у меня следующие вопросы:

  1. Если я использую поток (Qt), то куда мне поместить системный вызов select для мониторинга последовательного порта?
  2. Безопасен ли поток системного вызова select?
  3. Является ли это интенсивным процессором, потому что в моем приложении происходит много вещей, включая обновление графического интерфейса?

Пожалуйста, не возражайте, если эти вопросы кажутся вам смешными. Я никогда не использовал такой механизм для последовательной связи.


person rocknroll    schedule 26.06.2009    source источник


Ответы (2)


спецификация POSIX (выбрать) — это место, где можно найти select определение . Я лично рекомендую poll - у него лучший интерфейс и он может обрабатывать любое количество дескрипторов, а не установленное системой ограничение.

Если я правильно понимаю, вы активируете потоки на основе состояния определенных дескрипторов. Лучше было бы, чтобы каждый поток имел свой собственный дескриптор и сам вызывал select. Видите ли, select не изменяет состояние системы, и пока вы используете локальные переменные потока, это будет безопасно. Тем не менее, вам обязательно нужно убедиться, что вы не закрываете дескриптор, от которого зависит поток.

Использование select/poll с тайм-аутом оставляет «ожидание» на стороне ядра, что означает, что поток обычно засыпает. Пока поток спит, он не использует процессорное время. С другой стороны, цикл while/for для вызова select без тайм-аута даст вам более высокую загрузку ЦП, поскольку вы постоянно вращаетесь в цикле.

Надеюсь это поможет.

РЕДАКТИРОВАТЬ: Кроме того, select/poll могут иметь непредсказуемые результаты при работе с одним и тем же дескриптором в нескольких потоках. Простая причина этого заключается в том, что первый поток может быть разбужен, потому что дескриптор готов для чтения, а второй поток должен ждать следующего пробуждения, доступного для чтения.

Пока вы не работаете с одним и тем же дескриптором в нескольких потоках, у вас не должно возникнуть проблем.

person Matthew Iselin    schedule 26.06.2009
comment
Гуд информация!! Один вопрос. Как поток узнает, что ему нужно проснуться, если сокет fd готов выполнить операцию чтения/записи. Ядро прерывает поток? - person Sumit Trehan; 19.05.2013
comment
@SumitTrehan Ядро пробуждает поток, так как оно переводит поток в состояние готовности к выполнению, то есть поток запускается, как только получает процессорное время. - person Medicine; 14.08.2013

Это системный вызов — я думаю, он должен быть потокобезопасным.

Я не делал этого раньше, но я был бы весьма удивлен, если бы это было не так. Насколько интенсивен процессор select(), на мой взгляд, во многом зависит от количества файловых дескрипторов, которые вы ожидаете. select() в основном используется для ожидания готовности ряда (> 1) файловых дескрипторов.

Следует также отметить, что select() не следует использовать для опроса файловых дескрипторов — по соображениям производительности. Обычное использование: вы сделали свою работу, и может пройти некоторое время, пока не произойдет следующее. Теперь вы приостанавливаете свой процесс с помощью select и запускаете другой процесс. select() обычно приостанавливает активный процесс. Как это работает вместе с потоками, я не уверен! Я бы подумал, что весь процесс (и все потоки) приостановлен. Но это может быть задокументировано. Это также может зависеть (в Linux), используете ли вы системные потоки или пользовательские потоки. Ядро не будет знать User-Threads и, следовательно, приостановит весь процесс.

person Juergen    schedule 26.06.2009
comment
Это действительно не очень хороший ответ. Много догадок... Что такое User-Thread?! - person Alexis Wilke; 03.03.2018