it-swarm.com.ru

Состояние процесса Linux

В Linux, что происходит с состоянием процесса, когда ему нужно читать блоки с диска? Это заблокировано? Если да, то как выбрать другой процесс для выполнения?

83
Blair

В ожидании возврата read() или write() из/в дескриптор файла процесс будет помещен в особый вид сна, известный как "D" или "Дисковый спящий режим". Это особенное, потому что процесс не может быть убит или прерван в таком состоянии. Процесс, ожидающий возврата из ioctl (), также будет переведен в режим ожидания.

Исключением является случай, когда файл (например, терминал или другое символьное устройство) открывается в режиме O_NONBLOCK и передается, когда предполагается, что устройству (например, модему) потребуется время для инициализации. Однако вы указали блочные устройства в своем вопросе. Кроме того, я никогда не пробовал ioctl(), которая может блокировать fd, открытый в неблокирующем режиме (по крайней мере, сознательно).

Выбор другого процесса полностью зависит от используемого вами планировщика, а также от того, что другие процессы могли бы сделать, чтобы изменить свои веса в этом планировщике.

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

80
Tim Post

Когда процессу необходимо извлечь данные с диска, он фактически прекращает работу на ЦП, чтобы позволить другим процессам запускаться, потому что операция может занять много времени - обычное время поиска диска не менее 5 мс, а 5 мс - 10 млн. Циклы процессора, вечность с точки зрения программы!

С точки зрения программиста (также называемого "в пространстве пользователя"), это называется системным вызовом блокировки . Если вы вызываете write(2) (которая является тонкой оболочкой libc для системного вызова с тем же именем), ваш процесс точно не останавливается на этой границе; в ядре он продолжает выполнять код системного вызова. Большую часть времени он проходит вплоть до определенного драйвера контроллера диска (имя файла → файловая система/VFS → блочное устройство → драйвер устройства), где команда для извлечения блока на диске передается на соответствующее оборудование, которое является очень быстрая работа большую часть времени.

Затем процесс переводится в состояние сна (в пространстве ядра блокировка называется спящей - ничто никогда не "блокируется" с точки зрения ядра). Он будет пробужден после того, как аппаратное обеспечение окончательно выберет правильные данные, затем процесс будет помечен как работоспособный и будет запланирован. В конце концов, планировщик запустит процесс.

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

Можно вызвать большинство системных вызовов ввода/вывода в неблокирующем режиме (см. O_NONBLOCK в open(2) и fcntl(2)). В этом случае системные вызовы возвращаются немедленно и сообщают только об отправке операции на диске. Программист должен будет позже в явном виде проверить, успешно ли выполнена операция, успешно или нет, и извлечь ее результат (например, с помощью select(2)). Это называется асинхронным или основанным на событиях программированием.

Большинство ответов, в которых упоминается состояние D (которое в именах состояний Linux называется TASK_UNINTERRUPTIBLE), неверны. Состояние D - это специальный режим ожидания, который запускается только в пути кода пространства ядра, когда этот путь кода не может быть прервано (потому что это было бы слишком сложно для программирования), ожидая, что оно будет блокироваться только в течение очень короткого времени. Я считаю, что большинство "D-состояний" на самом деле невидимы; они очень недолговечны и не могут быть обнаружены такими инструментами, как "top".

Вы можете столкнуться с неубиваемыми процессами в состоянии D в нескольких ситуациях. NFS славится этим, и я сталкивался с этим много раз. Я думаю, что между некоторыми путями кода VFS существует семантическое противоречие, предполагающее, что они всегда достигают локальных дисков и быстрого обнаружения ошибок (на SATA время ожидания ошибки составляет около 100 мс), и NFS, которая на самом деле выбирает данные из сети, которые более устойчивый и имеет медленное восстановление (обычное время ожидания TCP - 300 секунд). Прочитайте эта статья для классного решения, представленного в Linux 2.6.25 с состоянием TASK_KILLABLE. До этой эры был хак, когда вы могли отправлять сигналы клиентам процесса NFS, отправляя SIGKILL в поток ядра rpciod, но забудьте об этом уродливом трюке…

123
zerodeux

Процесс, выполняющий ввод/вывод, будет переведен в состояние D (непрерывный режим сна) , который освобождает ЦП до тех пор, пока не произойдет аппаратное прерывание, сообщающее ЦП: вернитесь к выполнению программы. Смотрите man ps для других состояний процесса.

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

В ядре 2.6 есть O (1) планировщик сложности времени , поэтому независимо от того, сколько процессов запущено, процессоры будут назначаться в постоянное время. Тем не менее, это более сложно, поскольку в 2.6 введено вытеснение, а балансировка нагрузки на процессор - не простой алгоритм. В любом случае, он эффективен, и процессоры не будут простаивать, пока вы ожидаете ввода-вывода.

7
user224579

Как уже объяснили другие, процессы в состоянии "D" (непрерывный сон) ответственны за зависание процесса ps. Для меня это случалось много раз с RedHat 6.x и автоматически установленными домашними каталогами NFS.

Для отображения процессов в состоянии D вы можете использовать следующие команды:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

Чтобы узнать текущий каталог процесса и, возможно, подключенный диск NFS, у которого есть проблемы, вы можете использовать команду, аналогичную приведенной в следующем примере (замените 31134 номером спящего процесса):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

Я обнаружил, что передача команды umount с ключом -f (force) в соответствующую смонтированную файловую систему nfs смогла разбудить спящий процесс:

umount -f /auto/pippo

файловая система не была размонтирована, потому что она была занята, но связанный процесс проснулся, и я смог решить проблему без перезагрузки.

2
Valerio Di Giampietro

Да, задача блокируется в системном вызове read (). Выполняется другая задача, которая готова, или, если другие задачи не готовы, запускается задача ожидания (для этого ЦП).

Обычное блокирующее чтение диска приводит к тому, что задача переходит в состояние "D" (как уже отмечали другие). Такие задачи способствуют средней загрузке, даже если они не потребляют процессор.

Некоторые другие типы ввода-вывода, особенно ttys и сеть, не ведут себя одинаково - процесс заканчивается в состоянии "S" и может быть прерван и не учитывается при расчете средней нагрузки.

1
MarkR

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

Процессы, ожидающие завершения ввода-вывода, обычно отображаются в состоянии D, например, ps и top.

1
derobert

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

0
Martin v. Löwis

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

Решение о том, какой процесс будет запущен следующим, зависит от планировщик в ядре.

0
Benno