Ответ 1
Обратите внимание, что ваш вопрос сильно зависит от процессора; хотя нередко вы можете столкнуться с определенными процессорами, где эта концепция уровня пользовательского уровня/уровня ядра даже не существует.
Регистр cs имеет еще одну важную функцию: он включает в себя 2-битный которое указывает текущий уровень привилегий (CPL) CPU. значение 0 обозначает самый высокий уровень привилегий, а значение 3 обозначает самый низкий. Linux использует только уровни 0 и 3, которые соответственно называемый режимом ядра и пользовательским режимом.
(взято из "Понимание ядра Linux 3e", раздел 2.2.1)
Также обратите внимание, что это зависит от процессора, как вы можете ясно видеть, и он будет меняться от одного к другому, но концепция, как правило, выполняется.
Кто его устанавливает? Как правило, ядро /cpu и пользовательский процесс не могут его изменить, но позвольте мне что-то объяснить здесь.
Это чрезмерное упрощение, не принимайте его, как оно есть
Предположим, что ядро загружено и первое приложение только что началось (первая оболочка), ядро загружает все для запуска этого приложения, устанавливает бит в регистр cs (если вы используете x86), а затем переходит к коду процесса Shell.
В этом контексте оболочка будет продолжать выполнять все свои инструкции, если процесс содержит некоторую привилегированную инструкцию, процессор будет извлекать его и не будет выполнять; он предоставит исключение (аппаратное исключение), которое сообщает ядру, что кто-то попытался выполнить привилегированную инструкцию, и здесь код ядра обрабатывает задание (CPU устанавливает режим cs в режим ядра и переходит к некоторому известному местоположению для обработки этого типа ошибок (возможно, завершение процесса, возможно, что-то еще).
Итак, как процесс может сделать что-то привилегированное? Например, разговаривать с определенным устройством? Вот системные вызовы; ядро выполнит эту работу для вас.
Что происходит, так это следующее:
Вы устанавливаете то, что хотите в определенном месте (например, вы установили, что хотите получить доступ к файлу, местоположение файла - x, к которому вы обращаетесь для чтения и т.д.) В некоторых регистрах (документация ядра сообщит вам об этом) и затем (на x86) вы вызовете инструкцию int0x80
.
Это прерывает CPU, останавливает вашу работу, устанавливает режим в режим ядра, перескакивает регистр IP в известное местоположение, в котором есть код, который обслуживает запросы ввода-вывода и перемещается оттуда.
После того, как ваши данные будут готовы, ядро будет устанавливать эти данные в том месте, где вы можете получить доступ (расположение памяти, регистр, зависит от процессора/ядра/того, что вы запросили), устанавливает флаг cs в пользовательский режим и возвращается к ваша инструкция рядом с инструкцией int 0x80
.
Наконец, это происходит всякий раз, когда происходит переход, ядро получает уведомление о том, что происходит так, что процессор завершает вашу текущую инструкцию, изменяет статус CPU и переходит к тому, где код, который обрабатывает эту вещь; процесс, описанный выше, грубо говоря, относится к тому, как происходит переход между режимом ядра и пользовательским режимом.