2013-05-19 1 views
5

В многопоточной программе Linux, используемой для последовательной связи, возможно ли (и какой будет лучший подход) прекратить вызов блокировки read() из другого потока?Linux, отменить блокировку read()

Я хотел бы сохранить все как можно более реактивным и избежать использования тайм-аутов с повторным опросом.

Основой этого вопроса является то, что я пытаюсь создать библиотеку последовательной связи Scala для Linux с использованием JNI. Я пытаюсь сохранить родную сторону максимально простой, обеспечивая, среди прочего, функцию read() и close(). На стороне Scala один поток будет вызывать read() и блокировать до тех пор, пока не будут доступны данные из последовательного порта. Тем не менее, последовательный порт может быть закрыт другими способами, что приведет к вызову close(). Теперь, чтобы освободить заблокированный поток, мне как-то нужно будет отменить вызов для чтения системы.

+0

Связанный: https://stackoverflow.com/questions/384391/how-to-signal-select-to-return-immediately –

ответ

7

Один довольно популярный трюк: вместо блокировки в read() блокируйте в select() как на вашей последовательной розетке, так и на трубе. Затем, когда другой поток хочет разбудить ваш поток, он может сделать это, написав байт на другом конце этого канала. Этот байт заставит select() возвращаться, и ваш поток теперь может очищать и выходить или что-то еще, что ему нужно сделать. (Обратите внимание, что для того, чтобы эта работа была на 100% надежной, вы, вероятно, захотите, чтобы ваш последовательный сокет не блокировался, чтобы убедиться, что ваш поток блокируется только в select() и никогда не читается())

+1

прикомандированный. Я делаю почти все мои многопоточные программирования. Это закономерность прямо из сообщения последовательных процессов (CSP). Учитывая, что Scala действительно связывает объекты Scala (практическая реализация CSP), я думаю, что предложение очень подходит. Кстати, самый большой недостаток программирования для Windows Win32 или .NET заключается в том, что вы не можете выбрать() на трубах, массовое упущение. MS бы вы считаете, что Async IO лучше, но это приводит к действительно грязному коду. У проекта Cygwin возникли проблемы с написанием select(). Их решение включает в себя много потоков и опросов. – bazza

+0

FWIW вы можете сделать тот же трюк (всего лишь в 10 раз больше усилий;)) под Windows, создав два сокета TCP и подключив один из них к другому, как показано здесь: http://code.google.com /p/imagesoft/source/browse/trunk/rpcrt4/socketpair.c?r=5 –

+1

Спасибо за ответ! Выбор не работал для меня (возможно, я сделал что-то не так), однако при чтении man-страниц select() я наткнулся на poll(). Это сработало отлично :) –

4

Сигналы AFAIK - единственный способ разбить любой поток из системного вызова блокировки.

Используйте pthread_kill(), направленные на резьбу с сигналом USR1.

+0

Спасибо за ответ, но pthread_kill не будет возможен в моем случае использования (поскольку функции вызываются из различные потоки JVM). Есть ли какие-нибудь обходные пути, которые я мог бы использовать? Я слышал кое-что о epoll, но мои тесты тоже не работали. –

+0

Я не знаю достаточно о JNI, чтобы сделать рекомендацию. Вы можете использовать 'epoll' из одного потока и' close() 'из другого, но я считаю, что это неопределенное поведение. – kja

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

  • Нет связанных вопросов^_^