Что происходит в Linux с состоянием процесса, когда ему нужно прочитать блоки с диска? Это заблокировано? Если да, то как выбрать для выполнения другой процесс?
Во время ожидания read()
или write()
в / от возвращения дескриптора файла, то процесс будет помещен в особом виде сна, известный как «D» или «Disk Sleep». Это особенное, потому что процесс не может быть остановлен или прерван в таком состоянии. Процесс, ожидающий возврата от ioctl (), также будет переведен в спящий режим.
Исключением является ситуация, когда файл (например, терминал или другое символьное устройство) открывается в O_NONBLOCK
режиме, передаваемом, когда предполагается, что устройству (например, модему) потребуется время для инициализации. Однако в своем вопросе вы указали блочные устройства. Кроме того, я никогда не пробовал такой, ioctl()
который может блокировать fd, открытый в неблокирующем режиме (по крайней мере, сознательно).
Выбор другого процесса полностью зависит от используемого вами планировщика, а также от того, что другие процессы могли сделать для изменения своего веса в этом планировщике.
Известно, что некоторые программы пользовательского пространства при определенных обстоятельствах остаются в этом состоянии навсегда, до перезагрузки. Обычно они сгруппированы вместе с другими «зомби», но этот термин будет неправильным, поскольку технически они не прекратили свое существование.
Когда процессу необходимо получить данные с диска, он фактически перестает работать на ЦП, чтобы позволить другим процессам работать, потому что операция может занять много времени - обычно время поиска для диска составляет не менее 5 мс, а 5 мс - 10 миллионов. Циклы процессора, вечность с точки зрения программы!
С точки зрения программиста (также называемого «в пользовательском пространстве») это называется системным вызовом блокировки . Если вы вызываете
write(2)
(который представляет собой тонкую оболочку libc вокруг системного вызова с тем же именем), ваш процесс точно не остановится на этой границе; в ядре он продолжает выполнение кода системного вызова. В большинстве случаев все идет до конкретного драйвера контроллера диска (имя файла → файловая система / VFS → блочное устройство → драйвер устройства), где команда на выборку блока на диске отправляется соответствующему оборудованию, что очень сложно. большую часть времени быстрая работа.ЗАТЕМ процесс переводится в состояние сна (в пространстве ядра блокировка называется спящим - с точки зрения ядра ничего не блокируется). Он будет активирован, как только оборудование наконец получит нужные данные, затем процесс будет отмечен как работающий и будет запланирован. В конце концов, планировщик запустит процесс.
Наконец, в пользовательском пространстве системный вызов блокировки возвращается с надлежащим статусом и данными, и выполнение программы продолжается.
Можно ссылаться на большинство системных вызовов ввода / вывода в режиме без блокировки (см
O_NONBLOCK
вopen(2)
иfcntl(2)
). В этом случае системные вызовы немедленно возвращают и сообщают только об отправке операции с диском. Программист должен будет позже явно проверить, завершилась ли операция, успешно или нет, и получить ее результат (например, с помощьюselect(2)
). Это называется асинхронным программированием или программированием на основе событий.Большинство ответов здесь, в которых упоминается состояние D (которое вызывается
TASK_UNINTERRUPTIBLE
в именах состояний Linux), неверны. Состояние D - это специальный спящий режим, который запускается только в пути кода пространства ядра, когда этот путь кода не может быть прерван (потому что он был бы слишком сложным для программирования), с ожиданием, что он будет блокироваться только на очень долгое время. мало времени. Я считаю, что большинство «состояний D» на самом деле невидимы; они очень недолговечны и не могут быть обнаружены с помощью таких инструментов отбора проб, как «верх».В некоторых ситуациях вы можете столкнуться с неуничтожаемыми процессами в состоянии D. NFS славится этим, и я сталкивался с этим много раз. Я думаю, есть семантическое противоречие между некоторыми путями кода VFS, которые предполагают, что всегда достигают локальных дисков и быстро обнаруживают ошибки (на SATA тайм-аут ошибки составляет около нескольких 100 мс), и NFS, который фактически извлекает данные из сети, которая является более устойчивым и имеет медленное восстановление (обычно используется тайм-аут TCP в 300 секунд). Прочтите эту статью, чтобы узнать о крутом решении, представленном в Linux 2.6.25 с
TASK_KILLABLE
состоянием. До этой эры существовал хакер, позволяющий отправлять сигналы клиентам процессов NFS, отправляя SIGKILL потоку ядраrpciod
, но забыть об этом уродливом трюке ...источник
/proc/stat
?Процесс, выполняющий ввод-вывод, будет переведен в состояние D (непрерывный сон) , которое освобождает ЦП до тех пор, пока не произойдет аппаратное прерывание, которое сообщает ЦП вернуться к выполнению программы. См.
man ps
Другие состояния процесса.В зависимости от вашего ядра существует планировщик процессов , который отслеживает очередь выполнения процессов, готовых к выполнению. Вместе с алгоритмом планирования он сообщает ядру, какой процесс назначить какому процессору. Следует учитывать процессы ядра и пользовательские процессы. Каждому процессу выделяется временной интервал, который представляет собой кусок процессорного времени, который ему разрешено использовать. Как только процесс использует весь свой временной интервал, он помечается как просроченный и получает более низкий приоритет в алгоритме планирования.
В ядре 2.6 есть планировщик временной сложности O (1) , поэтому независимо от того, сколько процессов у вас запущено, он будет назначать процессоры в постоянное время. Однако это более сложно, поскольку 2.6 представила приоритетное прерывание и балансировка нагрузки ЦП - непростой алгоритм. В любом случае это эффективно, и процессоры не будут простаивать, пока вы ждете ввода-вывода.
источник
Как уже объяснялось другими, процессы в состоянии «D» (непрерывный сон) ответственны за зависание процесса ps. Со мной такое случалось много раз с RedHat 6.x и автоматическими домашними каталогами NFS.
Чтобы вывести список процессов в состоянии D, вы можете использовать следующие команды:
Чтобы узнать текущий каталог процесса и, возможно, смонтированный диск NFS, на котором есть проблемы, вы можете использовать команду, аналогичную приведенной в следующем примере (замените 31134 на номер спящего процесса):
Я обнаружил, что передача команды umount с переключателем -f (force) для связанной смонтированной файловой системы nfs смогла разбудить спящий процесс:
файловая система не была размонтирована, потому что была занята, но связанный с этим процесс проснулся, и я смог решить проблему без перезагрузки.
источник
Предполагая, что ваш процесс является одним потоком и вы используете блокировку ввода-вывода, ваш процесс будет блокироваться, ожидая завершения ввода-вывода. Ядро тем временем выберет другой процесс для запуска на основе удобства, приоритета, времени последнего выполнения и т. Д. Если нет других запускаемых процессов, ядро не будет запускать их; вместо этого он сообщит оборудованию, что машина простаивает (что приведет к снижению энергопотребления).
Процессы, ожидающие завершения ввода-вывода, обычно появляются в состоянии D, например,
ps
иtop
.источник
Да, задача блокируется системным вызовом read (). Выполняется другая готовая задача, или, если другие задачи не готовы, запускается неактивная задача (для этого ЦП).
Нормальное, блокирующее чтение с диска приводит к тому, что задача переходит в состояние «D» (как отмечали другие). Такие задачи увеличивают среднюю нагрузку, даже если они не используют процессор.
Некоторые другие типы ввода-вывода, особенно ttys и сеть, ведут себя иначе - процесс заканчивается в состоянии «S», может быть прерван и не учитывается при средней загрузке.
источник
Да, задачи, ожидающие ввода-вывода, блокируются, а другие задачи выполняются. Выбор следующей задачи выполняется планировщиком Linux .
источник
Обычно процесс блокируется. Если операция чтения выполняется для файлового дескриптора, помеченного как неблокирующий, или если процесс использует асинхронный ввод-вывод, он не будет блокироваться. Также, если у процесса есть другие потоки, которые не заблокированы, они могут продолжить работу.
Решение о том, какой процесс запускается следующим, принимает планировщик в ядре.
источник