В вычислительной технике переключение контекста — это процесс сохранения состояния процесса или потока , чтобы его можно было восстановить и возобновить выполнение в более поздней точке, а затем восстановить другое, ранее сохраненное состояние. [1] Это позволяет нескольким процессам совместно использовать один центральный процессор (ЦП) и является неотъемлемой функцией многопрограммной или многозадачной операционной системы . В традиционном ЦП каждый процесс — исполняемая программа — использует различные регистры ЦП для хранения данных и удержания текущего состояния запущенного процесса. Однако в многозадачной операционной системе операционная система переключается между процессами или потоками, чтобы разрешить выполнение нескольких процессов одновременно. [2] Для каждого переключения операционная система должна сохранить состояние текущего запущенного процесса, а затем загрузить следующее состояние процесса, которое будет запущено на ЦП. Эта последовательность операций, которая сохраняет состояние запущенного процесса и загружает следующий запущенный процесс, называется переключением контекста.
Точное значение фразы «переключение контекста» варьируется. В контексте многозадачности это относится к процессу сохранения состояния системы для одной задачи, так что эта задача может быть приостановлена, а другая задача возобновлена. Переключение контекста также может произойти в результате прерывания , например, когда задаче необходимо получить доступ к дисковому хранилищу , освобождая время ЦП для других задач. Некоторые операционные системы также требуют переключения контекста для перемещения между задачами пользовательского режима и режима ядра . Процесс переключения контекста может оказать негативное влияние на производительность системы. [3] : 28
Контекстные переключения обычно требуют больших вычислительных затрат, и большая часть дизайна операционных систем направлена на оптимизацию использования контекстных переключений. Переключение с одного процесса на другой требует определенного времени для выполнения администрирования — сохранения и загрузки регистров и карт памяти, обновления различных таблиц и списков и т. д. Что на самом деле задействовано в контекстном переключении, зависит от архитектур, операционных систем и количества совместно используемых ресурсов (потоки, принадлежащие одному процессу, совместно используют много ресурсов по сравнению с не связанными, не взаимодействующими процессами).
Например, в ядре Linux переключение контекста включает загрузку соответствующего блока управления процессом (PCB), хранящегося в таблице PCB в стеке ядра, для извлечения информации о состоянии нового процесса. Информация о состоянии ЦП, включая регистры, указатель стека и счетчик программ , а также информация об управлении памятью, такая как таблицы сегментации и таблицы страниц (если старый процесс не делит память с новым), загружаются из PCB для нового процесса. Чтобы избежать неправильной трансляции адресов в случае, если предыдущий и текущий процессы используют разную память, буфер трансляции (TLB) должен быть очищен. Это отрицательно влияет на производительность, поскольку каждая ссылка на память в TLB будет пропущена, поскольку он пуст после большинства переключений контекста. [4] [5]
Более того, аналогичное переключение контекста происходит между пользовательскими потоками , особенно зелеными потоками , и часто очень легковесно, сохраняя и восстанавливая минимальный контекст. В крайних случаях, таких как переключение между горутинами в Go , переключение контекста эквивалентно выходу сопрограммы , который лишь немного дороже вызова подпрограммы .
Существует три потенциальных триггера для переключения контекста:
Чаще всего в рамках некоторой схемы планирования один процесс должен быть отключен от ЦП, чтобы другой процесс мог работать. Это переключение контекста может быть вызвано процессом, делающим себя невыполнимым, например, ожиданием завершения операции ввода-вывода или синхронизации . В системе с упреждающей многозадачностью планировщик также может отключать процессы, которые все еще могут работать. Чтобы предотвратить нехватку процессорного времени у других процессов, упреждающие планировщики часто настраивают прерывание таймера на срабатывание, когда процесс превышает свой временной интервал . Это прерывание гарантирует, что планировщик получит управление для выполнения переключения контекста.
Современные архитектуры управляются прерываниями . Это означает, что если ЦП запрашивает данные с диска, например, ему не нужно ждать завершения чтения; он может отправить запрос (устройству ввода-вывода) и продолжить выполнение какой-либо другой задачи. Когда чтение завершено, ЦП может быть прерван (в данном случае аппаратным обеспечением, которое отправляет запрос прерывания на PIC ) и представлено чтение. Для прерываний установлена программа, называемая обработчиком прерываний , и именно обработчик прерываний обрабатывает прерывание с диска.
При возникновении прерывания оборудование автоматически переключает часть контекста (по крайней мере, достаточную для того, чтобы обработчик мог вернуться к прерванному коду). Обработчик может сохранять дополнительный контекст в зависимости от деталей конкретных конструкций оборудования и программного обеспечения. Часто изменяется только минимальная часть контекста, чтобы минимизировать время, затрачиваемое на обработку прерывания. Ядро не порождает и не планирует специальный процесс для обработки прерываний, но вместо этого обработчик выполняется в (часто частичном) контексте, установленном в начале обработки прерывания. После завершения обслуживания прерывания восстанавливается контекст, действовавший до возникновения прерывания, так что прерванный процесс может возобновить выполнение в своем надлежащем состоянии.
Когда система переходит между пользовательским режимом и режимом ядра , переключение контекста не обязательно; переход режима сам по себе не является переключением контекста. Однако, в зависимости от операционной системы, переключение контекста также может иметь место в это время.
Состояние текущего выполняемого процесса должно быть сохранено, чтобы его можно было восстановить при повторном планировании выполнения.
Состояние процесса включает все регистры, которые может использовать процесс, особенно счетчик программ , а также любые другие данные, специфичные для операционной системы, которые могут быть необходимы. Обычно это хранится в структуре данных, называемой блоком управления процессом (PCB) или switchframe .
PCB может храниться в стеке каждого процесса в памяти ядра (в отличие от стека вызовов пользовательского режима ), или для этой информации может существовать некоторая определенная операционной системой структура данных. Дескриптор PCB добавляется в очередь процессов, готовых к запуску, часто называемую очередью готовых .
Поскольку операционная система фактически приостановила выполнение одного процесса, она может затем переключить контекст, выбрав процесс из очереди готовых процессов и восстановив его PCB. При этом загружается счетчик программ из PCB, и, таким образом, выполнение может продолжиться в выбранном процессе. Приоритет процесса и потока может влиять на то, какой процесс будет выбран из очереди готовых процессов (т. е. это может быть очередь приоритетов ).
Детали различаются в зависимости от архитектуры и операционной системы, но это общие сценарии.
Рассмотрим общую арифметическую операцию сложения A = B+1. Инструкция сохраняется в регистре инструкций , а счетчик программ увеличивается. A и B считываются из памяти и сохраняются в регистрах R1, R2 соответственно. В этом случае B+1 вычисляется и записывается в R1 как окончательный ответ. Поскольку эта операция использует последовательные чтения и записи и нет ожиданий вызовов функций , следовательно, в этом случае не происходит переключения контекста/ожидания.
Предположим, что процесс A запущен и происходит прерывание таймера. Пользовательские регистры — счетчик программ, указатель стека и регистр состояния — процесса A затем неявно сохраняются ЦП в стеке ядра A. Затем оборудование переключается в режим ядра и переходит в обработчик прерываний, чтобы операционная система взяла управление на себя. Затем операционная система вызывает процедуру, switch()
чтобы сначала сохранить пользовательские регистры общего назначения A в стеке ядра A, затем она сохраняет текущие значения регистров ядра A в PCB A, восстанавливает регистры ядра из PCB процесса B и переключает контекст, то есть изменяет указатель стека ядра, чтобы он указывал на стек ядра процесса B. Затем операционная система возвращается из прерывания. Затем оборудование загружает пользовательские регистры из стека ядра B, переключается в пользовательский режим и запускает процесс B из счетчика программ B. [6]
Переключение контекста само по себе имеет издержки в производительности из-за запуска планировщика задач , сбросов TLB и косвенно из-за совместного использования кэша ЦП между несколькими задачами. [7] Переключение между потоками одного процесса может быть быстрее, чем между двумя отдельными процессами, поскольку потоки совместно используют одни и те же карты виртуальной памяти , поэтому сброс TLB не требуется. [8]
Время переключения между двумя отдельными процессами называется задержкой переключения процесса . Время переключения между двумя потоками одного и того же процесса называется задержкой переключения потока . Время от момента генерации аппаратного прерывания до момента его обслуживания называется задержкой прерывания .
Переключение между двумя процессами в операционной системе с одним адресным пространством может быть быстрее, чем переключение между двумя процессами в операционной системе с частными адресными пространствами для каждого процесса. [9]
Переключение контекста может выполняться в основном программным или аппаратным способом. Некоторые процессоры, такие как Intel 80386 и его последователи, [10] имеют аппаратную поддержку для переключения контекста, используя специальный сегмент данных, обозначенный как сегмент состояния задачи (TSS). Переключение задачи может быть явно запущено с помощью инструкции CALL или JMP, нацеленной на дескриптор TSS в глобальной таблице дескрипторов . Это может произойти неявно, когда срабатывает прерывание или исключение, если в таблице дескрипторов прерываний (IDT) есть шлюз задачи . Когда происходит переключение задачи, ЦП может автоматически загрузить новое состояние из TSS.
Как и в случае с другими задачами, выполняемыми на оборудовании, можно было бы ожидать, что это будет довольно быстро; однако, основные операционные системы, включая Windows и Linux , [11] не используют эту функцию. Это в основном связано с двумя причинами:
TS
— хотя бит автоматически включается в CR0
регистре управления , что приводит к сбою при выполнении инструкций с плавающей точкой и дает ОС возможность сохранять и восстанавливать состояние с плавающей точкой по мере необходимости).Переключение контекста лежит в основе жонглирования процессами. Оно состоит из остановки текущего вычисления, сохранения достаточного количества информации, чтобы его можно было перезапустить позже, и перезапуска другого процесса.