Как реализован системный вызов в Linux? - PullRequest
38 голосов
/ 31 января 2009

Когда я вызываю системный вызов в пользовательском режиме, как он обрабатывается в ОС?

Вызывает ли он какой-нибудь исполняемый двоичный файл или некоторую стандартную библиотеку?

Если да, что нужно для завершения вызова?

Ответы [ 6 ]

36 голосов
/ 31 января 2009

Посмотрите на это .

Начиная с версии 2.5, linux Ядро представило новый системный вызов механизм входа на Pentium II + процессоры. Из-за проблем с производительностью на процессорах Pentium IV с существующими метод программного прерывания, альтернативный ввод системного вызова механизм был реализован с использованием SYSENTER / SYSEXIT инструкции доступно на процессорах Pentium II +. Эта статья исследует этот новый механизм. Обсуждение ограничено архитектура x86 и весь исходный код списки основаны на ядре Linux 2.6.15.6.

  1. Что такое системные вызовы?

    Системные вызовы обеспечивают пользовательский интерфейс обрабатывает способ запроса услуг из ядра. Какого рода Сервисы? Услуги, которыми управляют операционной системой, такой как хранилище, память, сеть, управление процессами и т. д. Например, если пользовательский процесс хочет прочитать файл, ему придется сделать 'открыть' и 'прочитать' системные вызовы. Обычно системные вызовы не называются процессами напрямую. C библиотека обеспечивает интерфейс для всей системы вызовов.

  2. Что происходит при системном вызове?

    Фрагмент кода ядра запущен на запрос пользовательского процесса. Этот код работает в кольце 0 (с текущей привилегией уровень -CPL- 0), который является самым высоким уровень привилегий в x86 архитектура. Все пользовательские процессы запускаются в кольце 3 (CPL 3).

    Итак, для реализации механизма системных вызовов нам нужно

    1) способ вызова кода звонка 0 с звонка 3.

    2) некоторый код ядра для обслуживания запроса.

  3. Старый добрый способ сделать это

    Некоторое время назад Linux реализовать системные вызовы на всех x86 платформы, использующие программные прерывания. Чтобы выполнить системный вызов, пользовательский процесс скопирует нужный номер системного вызова в% eax и выполнит 'int 0x80'. Это сгенерирует прерывание 0x80 и процедура обработки прерывания будет называется. Для прерывания 0x80 это рутина "все системные вызовы рутина. Эта рутина будет выполнить в кольце 0. Эта процедура, как определено в файле /usr/src/linux/arch/i386/kernel/entry.S, сохранит текущее состояние и позвонит на основе соответствующего обработчика системных вызовов по значению в% eax.

  4. Новый блестящий способ сделать это

    Выяснилось, что это программное обеспечение метод прерывания был намного медленнее Процессоры Pentium IV. Чтобы решить это вопрос, Линус реализовал альтернативный механизм системного вызова воспользоваться SYSENTER / SYSEXIT инструкции, предоставляемые всеми Pentium II + процессоры. Прежде чем идти дальше с этим новым способом сделать это, давайте познакомиться с эти инструкции.

11 голосов
/ 01 февраля 2009

Это зависит от того, что вы подразумеваете под системным вызовом. Вы имеете в виду вызов библиотеки C (через glibc) или реальный системный вызов? Вызовы библиотеки C всегда заканчиваются системными вызовами.

Старый способ выполнения системных вызовов был через программное прерывание, то есть инструкцию int. В Windows было int 0x2e, в то время как в Linux int 0x80. ОС устанавливает обработчик прерываний для 0x2e или 0x80 в таблице дескрипторов прерываний (IDT). Этот обработчик затем выполняет системный вызов. Он копирует аргументы из пользовательского режима в режим ядра (это контролируется соглашением, специфичным для ОС). В Linux аргументы передаются с использованием ebx, ecx, edx, esi и edi. В Windows аргументы копируются из стека. Затем обработчик выполняет какой-то поиск (чтобы найти адрес функции) и выполняет системный вызов. После завершения системного вызова инструкция iret возвращается в режим пользователя.

Новый путь - sysenter и sysexit. Эти две инструкции в основном выполняют всю работу по регистрации за вас. ОС устанавливает инструкции через регистры, специфичные для модели (MSR). После этого это практически то же самое, что и использование int.

4 голосов
/ 31 января 2009

Он проходит через glibc, который выдает прерывание 0x80 после заполнения регистров параметрами. Затем обработчик прерываний ядра ищет системный вызов в таблице системных вызовов и вызывает соответствующую функцию sys _ * ().

2 голосов
/ 17 июля 2012

int X в сборке преобразуется в номер системного вызова n.
Ex read syscall может иметь номер 4.
При запуске системы ОС создает таблицу указателей, называемых таблицей дескрипторов прерываний (IDT), в которой есть список адресов для системных вызовов, а также привилегия, необходимая для их выполнения.
Текущий уровень привилегий (CPL) сохраняется в одном из битов регистра CS (технически 2 бита в x86).
Далее следуют инструкции int:
• Получить n-й дескриптор из IDT, где n - аргумент типа int.
• Убедитесь, что CPL в% cs равен <= DPL, где DPL - это уровень привилегий в дескрипторе. <br> • Если нет, то у пользователя не было достаточных привилегий для выполнения этого, и это приведет к выполнению инструкции int 13 (общая ошибка защиты) (у пользователя не было достаточных привилегий)
• Если да, то у пользовательского кода достаточно прав для выполнения этого системного вызова, текущий контекст выполнения сохраняется (регистрируется и т. Д.), Потому что теперь мы переключаемся в режим ядра.
Информация включает регистры, флаги, потому что когда системный вызов завершен, мы хотим продолжить выполнение с того места, где мы ушли. • Параметры системного вызова сохраняются в стеке ядра, поскольку системный вызов выполняется в режиме ядра.

VSYSCALL (БЫСТРЫЙ СИСТЕМНЫЙ ВЫЗОВ)
Каждый раз, когда пользователь выполняет системный вызов, Os сохраняет текущее состояние машины (т. Е. Регистр, указатель стека и т. Д.) И переключается в режим ядра для выполнения. Для какого-то системного вызова нет необходимости сохранять весь регистр. Ex gettime дня системный вызов считывает текущее время и системный вызов возвращается. Поэтому некоторые системные вызовы реализуются через так называемые vsyscalls. Здесь, когда выполняется системный вызов, он выполняется в самом пользовательском пространстве без переключения на ядро. Так что время сэкономлено.
Подробнее о vsyscall http://www.trilithium.com/johan/2005/08/linux-gate/
здесь а тут Кто-нибудь может понять, как работает gettimeofday?

2 голосов
/ 31 января 2009

Значительно упрощено, но при попытке доступа к зарезервированному адресу памяти происходит прерывание. Прерывание переключает контекст в режим ядра и выполняет код ядра (фактический системный вызов) от имени пользователя. После завершения вызова управление возвращается к пользовательскому коду.

0 голосов
/ 23 декабря 2013

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

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