2010-01-27 3 views
4

В Linux, если два потока созданы и оба они запущены, когда один из них вызывает recv() или любой системный вызов IO, который блокирует, когда нет данных, что произойдет со всем процессом?Что происходит с другим потоком, когда один поток блокируется?

Будет ли другой блок нити также? Я полагаю, это зависит от того, как реализована потоковая обработка. Если библиотека потоков находится в пользовательском пространстве, а ядро ​​полностью не знает о потоках внутри процесса, тогда процесс является объектом планирования и, следовательно, оба потока блокируются.

Кроме того, если другой поток не блокирует из-за этого, может затем его send() данные через тот же сокет, который блокирует recv нить? Дуплексный?

Любые идеи?

ответ

1

Вы абсолютно правы, что поведение блокировки будет зависеть от того, реализован ли поток в пространстве ядра или в пространстве пользователя. Если потоки реализованы исключительно в пользовательском пространстве (то есть ядро ​​полностью не связано с потоковой передачей), то любая блокирующая точка входа в ядро ​​должна быть обернута каким-то неблокирующим вариантом, который может имитировать блокирующую семантику для его вызова " нить "(например, используя AIO для отправки/recv-данных вместо блокировки, а обратный вызов завершения снова запустит поток).

В Linux (и любой другой существующей основной ОС, о которой я могу думать), потоки реализованы на уровне ядра или аналогичны, а блокирующий вызов в ядре будет не заставлять все остальные потоки блокировать.

Да, вы можете send() к разъему, для которого другая нить заблокирована на recv().

+0

Спасибо! довольно полный ответ. хороший звонок. – Figo

+0

Еще один вопрос: если данные попали в сокет до того, как поток вызывает recv(), будет ли поток фактически получать эти данные? – Figo

+0

Да. Это действительно единственный способ, которым это могло бы работать, в неблокирующих сокетах датаграмм. Несколько маленьких заметок, которые я намереваюсь быть полезными - один, вы можете поэкспериментировать с такими вещами довольно легко. Напишите небольшую программу, которая «примет» соединение, затем «поспает» некоторое время, а затем вызовет «recv» в новом соединении.Используйте 'nc' (netcat) или что-то, чтобы создать соединение с вашим сервером, и сразу же напишите некоторые данные. Вы увидите, что сервер получил те же данные, что и вы отправили. Второе примечание - это действительно третий отдельный вопрос о том, что обычно представляет собой вопрос на форуме ... –

2

Блокировка вызовов в одном потоке не должна влиять на другие потоки.

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

+0

Спасибо, тогда он падает на второй вопрос: может ли другой неблокирующий поток отправлять() данные через один и тот же сокет, а recv() блокирует другой? Предположим, что UDP. – Figo

2

Вполне возможно реализовать потоки в пользовательском пространстве, чтобы один поток мог действовать в то время как другой блок потока на вводе/выводе.

Неблокированная нить должна быть в состоянии отправить на сокет, в то время как другой поток блокирует его (я написал такой код).

+0

Спасибо, это отличная новость. – Figo

+0

Возможно только в том случае, если системные вызовы поддерживают неблокирующие вызовы для всего. Очень можно остановить все пользовательские потоки на что-то вроде fstat в течение нескольких секунд. –

+0

@ Zan Lynx: Он говорит о Linux, который имеет системные вызовы aio_read() и aio_write(), совместимые с POSIX(). –