2009-01-31 4 views
30

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

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

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

ответ

2

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

+0

Что такое код ядра, исполняемая бинарная, сборная или динамически связанная библиотека? – MainID

+0

Ядро - это запущенное ядро ​​вашей системы, то есть изображение ОС в памяти. – tvanfosson

29

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

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

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

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

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

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

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

    1) способ вызова кольцо 0 код из кольца 3.

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

  3. Хороший старый способ не делать это

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

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

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

3

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

10

Это зависит от того, что вы подразумеваете под системным вызовом. Вы имеете в виду вызов библиотеки 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.

+0

«Библиотечные вызовы C всегда заканчиваются использованием системных вызовов в конце». - любые ссылки на это? –

+0

@MywikiWitwiki Не * любой * вызов библиотеки C, но вызывает 'read',' write' и т. Д. Единственные причины, по которым они могут быть - если они даже существуют, - вызваны исключительно специализированными оптимизациями. Вы можете предположить, что они всегда переходят в режим ядра, если только вы не являетесь экспертом в области ядра с инновационными знаниями. –

2

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

VSYSCALL (FAST SYSTEM CALL)
Каждый системный вызов времени выполняется пользователем, Os сохраняет текущее состояние машины (т.е. регистр, указатель стека и т.д.) и переключается в режим ядра для выполнения , Для некоторого системного вызова нет необходимости сохранять весь регистр. Ex gettime дневного системного вызова считывает текущее время и возвращается системный вызов. Таким образом, некоторые системные вызовы реализуются через так называемые vsyscalls. Здесь, когда выполняется системный вызов, он выполняется в пользовательском пространстве, не переходя в ядро. Таким образом, время сохраняется.
Смотрите здесь подробную информацию о vsyscall http://www.trilithium.com/johan/2005/08/linux-gate/
и здесь Anyone can understand how gettimeofday works?

0

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

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