LINUX.ORG.RU

можно. нельзя делать ждущий syscall.
вообще-то твой обработчик сигнала работает в user-mode, но работает он перед тем, как твой прерванный сигналом syscall выйдет в user-mode, поэтому тебе в обработчике делать можно все. только вот здравый смысл говорит, что допустимы только "короткие" операции.

proff
()

p.s. ждущий - он же блокируемый.

proff
()

Конечно, можно.

Как блокирующий так и неблокирующий.

proff wrote:

> но работает он перед темб как твой прерванный > сигналом syscall выйдет в user-mode

Это неправда.

idle ★★★★★
()

что здесь вообще за бред написан??? обьясните пож. подробнее? какой- такой блокирующий системный вызов и что за сигнал syscall???

anonymous
()
Ответ на: комментарий от idle

странно видеть подобный "всплеск негодования" ;)))
если то, что я написал, не правда, тогда где же та самая правда? ПРИВЕДИ ЕЕ...
ты вообще-то понял, что я сказал? ;)))

p.s. "чиста" мысли вслух ;)))
замечаю иногда, что порой очень интересно читать то, что говорят некоторые люди, уповающие на свои "уникальные возможности"... иногда они считают, что если то, что говорят другие, не укладывается в их здравый смысл, то это "не правда и не может быть только потому, что этого быть не может". видимо случай с заявлением оратора idle (2002-06-21 09:56:36.171) - тот самый случай. не правда и все. без доказательств. мало того, что не уважительно к аудитории, так еще и ошибочно. я вот все время думаю, откуда это "человеческое желание" идет. откуда ростут его ноги... кто-нибудь хочет продолжить подобную философскую беседу? ;)))

p.s.s. чтобы мое утверждение о том, что idle был неправ не осталось бездоказательным, попробую провести маленькую логическую цепочку (не для idle, для аудитории стараюсь ;)).

итак, доказательство того, что обработчик сигнала работает в user-mode И перед тем, как основной код выскочит из прерванного syscall'a. для справки - syscall - он же system call - системный вызов - передача управления ядру, т.е. переход исполнения программы из user-mode в kernel-mode и обратно.

для программиста, работающего на уровне прикладных задач (а именно такими мы и является, когда пишем свои аппликухи) существует всего 2 режима работы программы user-mode и kernel-mode (чем они отличаются - читай соотв. литературу). у процесса таким образом есть два адресных пространства - одно для user-mode, другое для kernel-mode (очень упрощенно). раз это два адресных пространства, то данные из одного пространства не видны в другом и наоборот. таким образом, мы доказали, что обработчик сигнала не может работать в kernel-mode, т.к. в обработчике сигнала мы имеем доступ ко всем глобальным переменным user-mode.
теперь докажем, что обработчик сигнала работает до выхода "основного" кода из прерванного syscall'a. проводим натурный эксперимент, пишем прогу, которая читает из stdin ввод пользователя и имеет обработчик сигнала SIGINT. проверяем код возврата (сколько и чего мы прочитали из stdin). запускаем прогу. вводим текст с клавы. печатаем текст, который мы прочитали из stdin. теперь давим на CTRL+C - процесс получает SIGINT - обработчик сигнала выводит какую-то нами написанную строчку текста, потом выводится строчка текста, которая проверяет код возврата оператора чтения из stdin (errno у нас при этом ErrorINTerrupted). таким образом сначала работает signal handler, потом "основной" код.
что и требовалось доказать.

отвечаю на вопрос "как же тогда передаются параметры в syscall (т.е. из user-mode в kernel-mode и обратно)": есть соглашение о том, где находятся структуры данных, которые передаются между адресными пространствами, т.е. данные лежат "не где попало" а в строго определенном месте в строго определенной форме. этого соглашения достаточно для того, чтобы произвести обмен данными между пространствами.

пофилософствуем, товаришч idle? ;)))

proff
()

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

Я всего лишь написал, что неверно, что обработчик сигнала исполняется ПЕРЕД ТЕМ, КАК ПРЕРВАННЫЙ SYSCALL ВЫЙДЕТ В USER-MODE.

Он исполняется после того, как прерванный syscall завершится и, разумеется!!!, в user-mode.

После выполнения обработчика управление вернется в точку вызова int 80 (или, в случае SA_RESTART и возврата syscall ERESTARTSYS, вновь на эту же инструкцию), и приложение сможет увидеть EINTR.

> у процесса таким образом есть два адресных пространства - > одно для user-mode, другое для kernel-mode (очень упрощенно). > раз это два адресных пространства, то данные из одного > пространства не видны в другом и наоборот.

В Linux процесс имеет одно и то же адресное пространство в kernel и user mode (поэтому системные вызовы в linux такие быстрые), но с разными правами доступа. Так что процесс в user-mode не может читать данные ядра, а ядро данные процесса может, и по тем же адресам.

> "как же тогда передаются параметры в syscall (т.е. из user-mode > в kernel-mode и обратно)": есть соглашение о том, где находятся > структуры данных, которые передаются между адресными пространствами, > т.е. данные лежат "не где попало" а в строго определенном месте > в строго определенной форме.

Хотел вновь написать, что это неправда, но решил не рисковать. Это, конечно, правда, но "это место" называется регистрами.

Берегите нервы, товарищи!

idle ★★★★★
()
Ответ на: комментарий от idle

2 idle (*) (2002-06-22 11:23:45.228) >В Linux процесс имеет одно и то же адресное пространство в kernel и >user mode (поэтому системные вызовы в linux такие быстрые), но с >разными правами доступа. Так что процесс в user-mode не может читать >данные ядра, а ядро данные процесса может, и по тем же адресам.

Насколько я знаю это не совсем правда;) - ядро имеет одно и тоже адресное пространство, а процес нет;) Посколько адресное пространство процесса может дополняться, уменьшаться и тп (простейший пример shared memory - присоединяется к адресному пространству процесса). А все это пространство контролируется ядром;) По поводу syscalls ant int 80: Те данные которые могут поместится в регистрах (ну целые, етс) в них и передаются, области данных не передаются - передаются указатели на них, опять же в регистрах, а ядро имеет возможность чтения данных и адресного пространства процесса;) (но как известно не наобород)

В общем вопрос сложен и интересен - рекомендую сначала почитать нечто типа Linux internals, etc.

По поводу собственно обработчиков: Он вызывается перед передачей управления процессу. Выполнение происходит на уровне user-space и с правами процесса, но как бы отдельно - процесс в этот момент спит. Можно рассматривать обработчик как отдельную нить (что можно сделать на практике, см sigaction), выполняемую в результате поступления сигнала процессу и в то время как основной процес остановлен. Поскольку это "нить" - меры по синхронизации принимать весьма желательно. Кстати использование pthread_* вызовов в обработчике сигнала не безопасно (по крайней мере так сказано в описании;) )

Кстати, я тоже могу ошибаться;)

tvn
()

Привет, tvn.

> ядро имеет одно и тоже адресное пространство, а процес нет

Еще раз: при переключениях user/kernel modes процесс работает в ОДНОМ адресном пространстве, т.е. cr3 не переключается. Меняются только права доступа. Если какая-то переменная в программе видна по адресу 12345, то в kernel mode - в контексте ЭТОГО процесса - ее также можно читать по адресу 12345 - см. include/asm/uaccess.h.

Другое дело, что после переключения контекста (точнее, после switch_mm), по этому адресу будет лежать что-то другое, напр. SIGSEGV :)

> Посколько адресное пространство процесса может дополняться, уменьшаться и тп

> (простейший пример shared memory - присоединяется к адресному пространству процесса)

Да. для kernel/user mode одновременно.

> области данных не передаются - передаются указатели на них

Ну разумеется, в случае read(fd, buf, len) в регистре передается не сам буфер, а его адрес :)

> По поводу собственно обработчиков: Он вызывается перед передачей

> управления процессу. Выполнение происходит на уровне user-space

> и с правами процесса, но как бы отдельно - процесс в этот момент

> спит. Можно рассматривать обработчик как отдельную нить (что можно

> сделать на практике, см sigaction), выполняемую в результате поступления

>сигнала процессу и в то время как основной процес остановлен.

Нет. Во время выполнения обработчика процесс в состоянии TASK_RUNNING. Перед возвратом в user-mode (arch/i386/kernel/entry.S:syscall_exit) проверяется наличее сигнала и do_signal настроит стек для возврата не в в точку вызова int 80, а в адрес sighandler. См. arch/i386/kernel/signal.c:setup_frame. Стек возврата для обработчика будет показывать на sys_sigreturn (trampoline для signal unblocking etc...) и далее вести к инструкции после int 80 (или, в случае SA_RESTART, опять на нее - handle_signal(): regs->eip -= 2).

Так что обработчик сигнала всегда выполняется в обычном контексте, только заблокированы sigaction.sa_mask.

Что касается pthreads - это другая тема. Это к вопросу синхронизации при clone(CLONE_VM).

Пока.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.