2010-06-26 4 views
12

Я работаю через главу о iPhone аудио и наткнулся раздел кода, который я не могу понять смысл:Зачем использовать select() вместо sleep()?

while (aqc.playPtr < aqc.sampleLen) 
{ 
    select(NULL, NULL, NULL, NULL, 1.0); 
} 

(Full code sample is on pages 163-166). Из того, что я понимаю в коде, аудио обрабатывается в другом потоке, и цикл while находится там, чтобы предотвратить прерывание основного потока, пока звук все еще обрабатывается.

Я не понимаю, почему select() используется вместо sleep().

Из того, что я читал select(), используется для мониторинга изменений ввода-вывода и передачи его. NULL не делает ничего значимого. Я запустил код с помощью sleep(), и он работает так, как ожидалось. (Мое знание низкого уровня POSIX практически несуществующее.)

+0

страшно. Я не знал, что люди все еще используют этот старый трюк. И это на кажущейся новой и блестящей архитектуре, где должно быть доступно много других средств для «сна». стыд за программиста/запись такого кода. –

+5

@JensGustedt не так страшно, как передача «double» в качестве параметра, когда функция ожидает ** указателя ** на 'struct timeval' – JeremyP

+0

@JensGustedt. Это на самом деле очень безопасный способ сна, потому что sleep() может не работа, например в обработчике сигналов. – LubosD

ответ

17

Выберите разрешить точное подсевое ожидание и более переносимое, чем сон. Есть и другие способы подождать, см. this question.

Но параметр таймаута select не должен быть float, а указателем на struct timeval. Я удивлен кодом, который вы показываете, даже компилируется. Дополнительно: этот странный условный выбор сопровождается безусловным сном (1). Мне кажется бессмысленным.

9

Использование select() с NULLrfds, wfds и efds это идиоматический способ переносимым спать с субсекундным разрешением.

+1

Но не является ли 'timeout' (5-й аргумент) предположительным (возможно, NULL) указателем на' struct timeval'? –

+0

@Matthew да, правильный. – ninjalj

+0

@MatthewFlaschen И в этом случае он будет спать вечно. –

-1

Нет причин для этого. Нет никакой причины спать(). Всегда следует ожидать, по крайней мере, одного запроса завершения программы - программы.

+0

Я не вижу, что с этим связано. Запрос на выключение вызовет 'SIGTERM', который обрабатывается обработчиком сигнала, по умолчанию или иным образом. –

+2

Это не отвечает на вопрос и не имеет большого смысла ... есть много веских причин спать, особенно на встроенных платформах (на мой взгляд, половина из них включает iPhone) –

+0

Я согласен с Павлом ... почти никогда не бывает причин для вызова Sleep() (за исключением, возможно, временной меры отладки). Любой поток, который заблокирован в Sleep(), не может быть отключен до тех пор, пока он не проснется, что делает остановку излишне медленной. (Возвращение Sleep() в ответ на входящий сигнал - это обход для этого, но смешивание сигналов и нескольких потоков - неприятный пакет червей, который лучше избегать). Лучше использовать подход, основанный на событиях, и блокировать что-то, что может быть разблокировано входящим событием, например. Выбрать(). –

4

Ну, сон (3) может быть реализован с использованием сигналов. Это зависит от платформы.

Когда вы используете select (2) и poll (2), вы знаете, что никакие сигналы не будут задействованы, что часто очень полезно. Например, если вы используете будильник (2), вы также не должны использовать сон (3), потому что «смешение звонков на будильник и сон - плохая идея» (согласно странице руководства.)

Кроме того, выбор и опрос дают вам миллисекундную детализацию во время сна, но сон имеет только зернистость в секундах.

3

Когда вы используете сигнал SIGALM в своем приложении и используете функции (u)sleep, когда SIGALRM появляется программа, немедленно возвращайтесь из функции ожидания, поэтому лучший способ спящего - подождать select.

struct timeval tv; 

tv.tv_sec = 1; 
tv.tv_usec = 1000; 

do 
{ 
    ret = select(1, NULL, NULL, NULL, &tv); 
} 
while((ret == -1)&&(errno == EINTR)); //select is interruped too 
+0

Выбирает ли отрегулировать 'tv' в течение прошедшего времени? Если нет, то цикл ожидания перезапускает весь временной интервал в каждом событии 'EINTR'. –

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