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

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


person Blair    schedule 25.09.2009    source источник


Ответы (8)


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

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

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

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

person Tim Post♦    schedule 25.09.2009
comment
Процесс, ожидающий возврата от ioctl (), также будет переведен в спящий режим. Я просто убил свой процесс пользовательского пространства, ожидая блокирующего IOCTL, так что это неправда. Если я не понимаю - person Hamzahfrq; 28.10.2015
comment
Было бы чрезвычайно трудно рассчитать время для такого испытания. Непрерывные процессы невозможно убить; если вы смогли убить его, то это была просто блокировка (ядро не было в середине какой-либо части ioctl и скопировало любой соответствующий ответ в пользовательское пространство в том месте, которое вы прошли (или, по крайней мере, не было в середина копирования)). Linux также сильно изменился с 2009 года, когда это было написано; это явление гораздо менее заметно, чем когда-то. - person Tim Post♦; 09.03.2016

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

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

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

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

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

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

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

person zerodeux    schedule 13.07.2011
comment
+1 за подробный ответ, но обратите внимание, что в этой ветке есть принятый ответ в течение почти двух лет. Нажмите на ссылку "Вопросы", если хотите помочь в ответах на новые вопросы. Добро пожаловать в Stack Overflow и спасибо за ваш вклад! - person GargantuChet; 14.07.2011
comment
Это единственный ответ, в котором упоминается NFS, которая в некоторых средах является наиболее распространенным объяснением процессов в состоянии D. +1. - person Pinko; 06.12.2011
comment
Очень хороший ответ, спасибо. Также обратите внимание, что процесс переходит в состояние D во время ожидания страниц, которые были выгружены, поэтому процесс перебоя будет находиться в состоянии D долгое время. - person cha0site; 12.05.2012
comment
@zerodeux хороший ответ, но я думаю, что ваша схема (имя файла - ›файловая система / VFS -› блочное устройство - ›драйвер устройства) должна быть (имя файла -› VFS - ›файловая система (ext3) -› блочное устройство - ›драйвер устройства) - person c4f4t0r; 24.05.2014
comment
Можно ли предположить, что время, потраченное ядром на ожидание спин-блокировок (которые могут или не могут быть связаны с дисковым вводом-выводом), все сообщается как D-состояние в /proc/stat? - person wick; 09.10.2016
comment
Другой случай состояния D: файловые системы Slow FUSE. - person Jonathon Reinhart; 14.01.2018

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

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

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

person user224579    schedule 25.09.2009

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

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

person Valerio Di Giampietro    schedule 02.08.2016

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

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

person derobert    schedule 25.09.2009
comment
Я запустил несколько процессов, используя около 10% общей памяти. Я заметил, что многие из них находятся в состоянии D. Это связано с медленным вводом-выводом на этой конкретной машине? Скажем, у меня 9 процессов, они могут конкурировать за ввод-вывод, и многие из них находятся в состоянии D. - person Kemin Zhou; 20.07.2017
comment
@KeminZhou По сравнению со скоростью процессора, ввод-вывод довольно медленный - даже быстрый ввод-вывод. Один тяжелый процесс ввода-вывода может легко занять магнитный диск, даже SSD. 10 тяжелых процессов ввода-вывода могут быть заняты довольно многими. - person derobert; 20.07.2017

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

Нормальное, блокирующее чтение с диска приводит к тому, что задача переходит в состояние «D» (как отмечали другие). Такие задачи увеличивают среднюю нагрузку, даже если они не используют ЦП.

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

person MarkR    schedule 25.09.2009

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

person Martin v. Löwis    schedule 25.09.2009

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

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

person Benno    schedule 25.09.2009