Linux-процессы

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

Как уже объяснялось другими, процессы в состоянии "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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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

Ответ 8

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

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