Внутренние системные вызовы Linux
Что происходит (подробно), когда поток выполняет системный вызов, поднимая прерывание 80? Какую работу делает Linux для стека потоков и другого состояния? Какие изменения внесены в процессор, чтобы перевести его в режим ядра? После запуска обработчика прерываний, как управление возвращается к вызывающему процессу?
Что делать, если системный вызов не может быть выполнен быстро: например. чтение с диска. Как обработчик прерывания отказывается от управления, чтобы процессор мог делать другие вещи во время загрузки данных и как он снова получает контроль?
Ответы
Ответ 1
Курс сбоя в режиме ядра в одном ответе
Хорошие вопросы! (Интервью вопросы?)
- Что происходит (подробно), когда
thread делает системный вызов, поднимая
прерывание 80?
Операция int $80 смутно напоминает вызов функции. ЦП "берет ловушку" и перезапускается по известному адресу в режиме ядра, как правило, с другим режимом MMU. Ядро сохранит многие регистры, но не нужно сохранять регистры, которые программа не ожидала бы обычного вызова функции для сохранения.
- Что делает Linux для
стек стека и другое состояние?
Обычно ОС сохраняет регистры, которые ABI promises не изменяется во время вызовов процедур. Стек останется неизменным; ядро будет запускаться в стеке ядра на потоке, а не в стеке каждого потока. Естественно, какое-то состояние изменится, иначе не было бы причин для системного вызова.
- Какие изменения внесены в
процессор, чтобы перевести его в режим ядра?
Это обычно полностью автоматическое. CPU имеет, как правило, инструкцию по программному прерыванию, которая немного похожа на операцию функционального вызова. Это приведет к переключению в режим ядра в контролируемых условиях. Как правило, процессор меняет какой-то бит защиты PSW, сохраняет старые PSW и ПК, запускается с известного вектора-вектора-ловушки и может также переключиться на другую защиту и сопоставление управления памятью.
- После запуска обработчика прерываний,
как управление возвращается обратно в
вызывающий процесс?
Будет какая-то команда "возврат от прерывания" или "возврат из ловушки", как правило, которая будет немного похожа на сложную инструкцию функции-возврата. Некоторые RISC-процессоры выполняли очень мало и требовали специального кода для возврата, а некоторые процессоры CISC, такие как x86, имели (никогда не использовавшиеся) инструкции, которые выполняли бы десятки операций, задокументированных на страницах псевдо-кода с архитектурой для корректировки возможностей.
- Что делать, если системный вызов не может быть
быстро завершается: например. чтение из
диск. Как обработчик прерываний
отказаться от контроля, чтобы
процессор может делать другие вещи, пока
данные загружаются и как это делается
затем снова получить контроль?
Ядро само по себе имеет многопоточность, как многопоточная программа пользователя. Он просто переключает стеки (потоки) и некоторое время работает над кем-то другим процессом.
Ответ 2
Чтобы ответить на последнюю часть вопроса - что делает ядро, если системный вызов нужно спать -
После системного вызова ядро по-прежнему логически работает в контексте той же задачи, что и системный вызов - это только в режиме ядра, а не в пользовательском режиме - это НЕ отдельный поток, и большинство системных вызовов не вызывают логики из другой задачи/потока. Случается, что системный вызов вызывает wait_event или wait_event_timeout или какую-либо другую функцию ожидания, которая добавляет задачу в список задач, ожидающих чего-то, затем ставит задачу в спящий режим, который меняет свое состояние, и вызывает расписание(), чтобы отказаться от него текущий процессор.
После этого задача не может быть запущена снова до тех пор, пока она не проснется, как правило, другой задачей (задача ядра и т.д.) или обработчиком прерываний, вызывающим функцию wake *, которая пробудит задачу (задачи), ожидающие этого конкретного события, что означает, что планировщик скоро планирует их снова.
Стоит отметить, что задачи пользовательского пространства (то есть потоки) являются только одним типом задачи, а внутри ядра также есть несколько других, которые могут работать, - это потоки ядра и нижние половинные обработчики/задачи/очереди задач и т.д.. В них делается работа, которая не принадлежит к какому-либо конкретному процессу пользовательского пространства (например, сетевая обработка, например, реакция на пинги). Эти задачи позволяют переходить в спящий режим, в отличие от прерываний (которые не должны вызывать планировщик)
Ответ 3
http://tldp.org/LDP/khg/HyperNews/get/syscall/syscall86.html
Ответ 4
Это должно помочь людям, которые ищут ответы на то, что происходит, когда выполняется команда syscall
, которая передает управление ядру (режим пользователя в режим ядра). Это основано на архитектуре x86_64.
https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-2.html