LINUX.ORG.RU

Висит ли процесс на выполнении системного вызова?


0

0

Hi!

Очевидно, что произвольный процесс может "навечно" заблокироваться
на выполнении системного вызова при определенных условиях.
Простейшие примеры - read, select, epoll_wait, futex.

Возникла очень просто формулируемая задача, простое решение которой
в голову не приходит.
Имеем процесс с определенным PID'ом.
Требуется определить, висит ли данный процесс на каком-либо системном
вызове или нет.
Критерием зависания будем считать выполнение системного вызова более
некоторого таймаута (например T=30 секунд).

Таким образом, если процесс закончил выполнение хотя бы одного
системного вызова, то считаем, что он не висит.
Если же за время наблюдения T процесс так и не завершил выполнение
системного вызова, то считаем, что он висит.

Понятное дело, что процесс может вообще не выполнять никаких системных
вызовов долгое время (например при долгих вычислениях).
Также очевидно, что процесс может получить сигнал, обработать его и
перезапустить системный вызов, обнаружив EINTR.
Все это можно игнорировать.

Есть идеи как решить данную проблему?

P.S.

Все решения, приходящие в голову, так или иначе построены вокруг
strace и ее реализации.
Мне они не очень нравятся, но если альтернатив не будет, придется
использовать.

Думаю, что правильно делать через ptrace и производные. Если нужны еще идеи: 1) Смотреть статистику user jiffies для данного процесса в /proc 2) С помощью LD_PRELOAD перехватывать интересующие системные вызовы

rmap
()

Пусть об этом позаботится Linux :)

dimon555 ★★★★★
()

отслеживать изменение переключений контекста через /proc/$PID/status

voluntary_ctxt_switches: nonvoluntary_ctxt_switches:

Каждый переход процесса в режим ядра (системный вызов) - это переключение контекста.

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

Всем спасибо за советы!
Буду экспериментировать.

Krivenok_Dmitry
() автор топика

> Критерием зависания будем считать выполнение системного вызова более > некоторого таймаута (например T=30 секунд).

Вот я запустил интерактивно bash и ушёл пить чай. Причём не на 1-5 минут, а пошёл греть самовар. Выходит, что пол-часа bash'у так и не вернулся read(). Но ведь bash не висит, верно?

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

>Но ведь bash не висит, верно?

Имеется ввиду не зависание программы из-за какой-либо проблемы,
а просто зависание на системном вызове.

Поэтому пример с bash'ем (который просто ждет ввода) и пример с
намертво зависшей программой в данном случае эквивалентны.

Krivenok_Dmitry
() автор топика
Ответ на: комментарий от bvvv

а ты вообще-то в курсе, что (почти) любой запрос ресурса вытесняем?

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

> Каждый переход процесса в режим ядра (системный вызов)
> - это переключение контекста.


нет, это неверно.

..._ctxt_switches никакого отношения к user/kernel mode
не имеют, они просто (в сумме) равны количеству вызовов
этим thread'ом schedule().

но следить за ними можно, если не меняются - значит task
"offline".

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

К сожалению следить за изменением *_ctxt_switches в моем случае нельзя, т.к. в старых ядрах серии 2.6.x (например 2.6.9) их нет в файле /proc/<PID>/status.

Krivenok_Dmitry
() автор топика
Ответ на: комментарий от Krivenok_Dmitry

Ну вы блин абстракциями занимаетесь. Условно считается, что выполнение любого системного вызова занимает 0 единиц времени (он выполняется почти мгновенно). По этой причине "висеть" системный вызов не может по определению. Зато он может перевести процесс в спящее состояние. А потом вывести его через некоторое время. Это ты в своей программе можешь написать while(true);. А за такой код в ядре руки надо отрывать. Ни один нормальный драйвер в рамках системного вызова НЕ ДОЛЖЕН делать НИ ОДНОЙ длительной по времени операции.

Коротко говоря нормально написанный системный вызов "висеть" не будет НИ ПРИ КАКИХ УСЛОВИЯХ. Правда, повторюсь, он может перевести процесс в спящее состояние. А потом вывести его в рабочее состояние.

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