[sisyphus] Q: Очень непростой вопрос на тему select() и сигналов

Sergey Vlasov vsu на altlinux.ru
Пт Апр 10 16:36:04 MSD 2009


On Fri, Apr 10, 2009 at 01:40:09PM +0400, Mikhail Efremov wrote:
> On Friday 10 April 2009 05:50:01 Michael Pozhidaev wrote:
> > Трюк с pipe(), чтобы проинформировать о сигнале пока трогать не буду.

Тем не менее этот "трюк" обеспечивает совместимость с наибольшим
количеством систем (не только различных версий Linux).

> Все так, это гарантируется стандартом. Вот только стандарт стандартом, а его 
> конкретная реализация - это конкретная реализация, в той или иной степени 
> этот стандарт поддерживающая. Раньше в Linux не было системного вызова  
> pselect, была эмуляция в glibc, проблемы не решающая. Начиная с 2.6.какой-то 
> версии ядра такой вызов есть, но я не знаю как он работает. Впрочем, не 
> думаю, что есть смысл делать системный вызов, не решающий проблему с race. 
> Может кто из знатоков ядра скажет по этому поводу больше.

Для архитектуры i386 системные вызовы pselect6 и ppoll были добавлены в
ядро в версии 2.6.16, для x86_64 - только в версии 2.6.19 (хотя номера
системных вызовов в asm/unistd.h были зарезервированы ещё в 2.6.16).
Однако имеет значение ещё и версия и детали сборки glibc - совсем старые
версии glibc (до 2.5) предоставляли только бесполезную эмуляцию pselect,
начиная с glibc-2.5, предусмотрена поддержка настоящего системного вызова,
но с автоматическим переключением на эмуляцию, если ядро слишком старое и
возвращает ошибку ENOSYS; кроме того, во время сборки должен быть доступен
asm/unistd.h с определением __NR_pselect6.  В результате всего этого
определить, что при вызове программой функции pselect() действительно
используется этот системный вызов, затруднительно (даже при наличии
достаточно свежего ядра можно получить эмуляцию либо на древней версии
glibc, либо даже на новой, но собранной со старыми заголовками ядра).

В Linux есть и другие способы работы с сигналами совместо с select(), не
имеющие проблем с эмуляцией, не гарантирующей правильную работу:

 - Вариация на тему pipe() - для оповещения основного цикла о пришедшем
   сигнале можно использовать дескриптор eventfd, требующий несколько
   меньше ресурсов, чем pipe; системный вызов доступен начиная с ядра
   2.6.22 (для i386 и x86_64); можно достаточно легко написать код,
   использующий eventfd при наличии его поддержки, но автоматически
   переключающийся на pipe при обнаружении устаревшего ядра или glibc.

 - signalfd - позволяет перевести сигналы в готовность файловых
   дескрипторов; системный вызов доступен начиная с ядра 2.6.22 (для i386
   и x86_64), поддержка в glibc - начиная с версии 2.8; в ядре 2.6.25 была
   исправлена обработка сигналов, переданных через sigqueue().
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : отсутствует
Тип     : application/pgp-signature
Размер  : 189 байтов
Описание: Digital signature
Url     : <http://lists.altlinux.org/pipermail/sisyphus/attachments/20090410/6776c2f6/attachment.bin>


Подробная информация о списке рассылки Sisyphus