В вычислении, А системный вызов (обычно сокращенно системный вызов) является программным способом, в котором компьютерная программа запрашивает услугу от ядра из операционной системы, на которой она выполняется. Это может включать службы, связанные с оборудованием (например, доступ к жесткому диску или доступ к камере устройства), создание и выполнение новых процессов, а также связь со встроенными службами ядра, такими как планирование процессов. Системные вызовы обеспечивают важный интерфейс между процессом и операционной системой.
В большинстве систем системные вызовы могут выполняться только из процессов пользовательского пространства, в то время как в некоторых системах, например OS / 360 и последующих версиях, привилегированный системный код также выдает системные вызовы.
Архитектура большинство современных процессоров, за исключением некоторых встраиваемых систем, включает в себя модель безопасности. Например, модель колец определяет несколько уровней привилегий, на которых может выполняться программное обеспечение: программа обычно ограничена своим собственным адресным пространством, так что она не может получить доступ или изменить другие запущенные программы или саму операционную систему, и обычно не может напрямую манипулировать аппаратные устройства (например, буфер кадра или сетевые устройства).
Однако многим приложениям необходим доступ к этим компонентам, поэтому системные вызовы предоставляются операционной системой для обеспечения четко определенных и безопасных реализаций таких операций. Операционная система работает с наивысшим уровнем привилегий и позволяет приложениям запрашивать услуги через системные вызовы, которые часто инициируются через прерывания. Прерывание автоматически переводит ЦП на некоторый повышенный уровень привилегий, а затем передает управление ядру, которое определяет, следует ли предоставить вызывающей программе запрошенную услугу. Если услуга предоставляется, ядро выполняет определенный набор инструкций, над которыми вызывающая программа не имеет прямого контроля, возвращает уровень привилегий на уровень вызывающей программы, а затем возвращает управление вызывающей программе.
Обычно системы предоставляют библиотеку или API, которые находятся между обычными программами и операционной системой. В Unix-подобных системах этот API обычно является частью реализации библиотеки C (libc), такой как glibc, которая предоставляет функции оболочки для системных вызовов, часто называемых так же, как системные вызовы, которые они вызывают. В Windows NT этот API является частью собственного API в библиотеке ntdll.dll ; это недокументированный API, используемый реализациями обычного Windows API и непосредственно используемый некоторыми системными программами в Windows. Функции оболочки библиотеки предоставляют обычное соглашение о вызове функций ( вызов подпрограммы на уровне сборки ) для использования системного вызова, а также для того, чтобы сделать системный вызов более модульным. Здесь основная функция оболочки состоит в том, чтобы поместить все аргументы, передаваемые системному вызову, в соответствующие регистры процессора (а также, возможно, в стек вызовов ), а также установить уникальный номер системного вызова для вызова ядра.. Таким образом, библиотека, которая существует между ОС и приложением, увеличивает переносимость.
Сам вызов библиотечной функции не вызывает переключения в режим ядра и обычно является обычным вызовом подпрограммы (с использованием, например, инструкции сборки "CALL" в некоторых архитектурах набора команд (ISA)). Фактический системный вызов передает управление ядру (и в большей степени зависит от реализации и платформы, чем абстрагирующий его вызов библиотеки). Например, в Unix-подобных системах, fork
и execve
являются C библиотечные функции, которые, в свою очередь выполнить инструкции, которые вызывают эти fork
и exec
системные вызовы. Выполнение системного вызова непосредственно в коде приложения является более сложным и может потребовать использования встроенного ассемблерного кода (в C и C ++ ), а также требует знания низкоуровневого двоичного интерфейса для операции системного вызова, что может быть предметом изменяться с течением времени и, таким образом, не быть частью двоичного интерфейса приложения ; библиотечные функции предназначены для того, чтобы абстрагироваться от этого.
В системах на основе exokernel библиотека особенно важна как посредник. На экзоядрах библиотеки защищают пользовательские приложения от API ядра очень низкого уровня и обеспечивают абстракции и управление ресурсами.
OS / 360 и DOS / 360 IBM реализуют большинство системных вызовов через библиотеку макросов на языке ассемблера, хотя есть несколько служб со связью вызовов. Это отражает их происхождение в то время, когда программирование на языке ассемблера было более распространенным, чем использование языка высокого уровня. Поэтому системные вызовы IBM не могли напрямую выполняться программами на языке высокого уровня, но требовали вызываемой подпрограммы-оболочки на языке ассемблера. С тех пор IBM добавила множество сервисов, которые можно вызывать из языков высокого уровня, например, в z / OS и z / VSE.
На Unix, Unix-подобных и других POSIX - совместимые операционные системы, популярные системные вызовы open
, read
, write
, close
, wait
, exec
, fork
, exit
, и kill
. Многие современные операционные системы имеют сотни системных вызовов. Например, Linux и OpenBSD имеют более 300 различных вызовов, NetBSD - около 500, FreeBSD - более 500, Windows - около 2000, разделенных между системными вызовами win32k (графический) и ntdll (ядро), а Plan 9 - 51.
Такие инструменты, как Трассирование, ftrace и фермы позволяют процесс выполнения от начала и сообщать обо все системных вызовах процесса вызываемой программы, или может подключаться к уже запущенному процессу и перехватывать любой системный вызов, сделанный указанным способом, если операция не нарушает права пользователя. Эта особая способность программы обычно также реализуется с помощью системных вызовов, таких как ptrace, или системных вызовов файлов в procfs.
Реализация системных вызовов требует передачи управления из пользовательского пространства в пространство ядра, что включает в себя какую-то особенность, зависящую от архитектуры. Типичный способ реализации этого - использование программного прерывания или прерывания. Прерывания передают управление ядру операционной системы, поэтому программному обеспечению просто необходимо настроить некоторый регистр с необходимым номером системного вызова и выполнить программное прерывание.
Это единственный метод, предусмотренный для многих процессоров RISC, но архитектуры CISC, такие как x86, поддерживают дополнительные методы. Например, набор инструкций x86 содержит инструкции SYSCALL
/ SYSRET
и SYSENTER
/ SYSEXIT
(эти два механизма были независимо созданы AMD и Intel соответственно, но по сути они делают то же самое). Это «быстрые» инструкции передачи управления, которые предназначены для быстрой передачи управления ядру для системного вызова без накладных расходов, связанных с прерыванием. Linux 2.5 начал использовать это на x86, где это было возможно; раньше он использовал INT
инструкцию, в которой номер системного вызова помещался в EAX
регистр перед выполнением прерывания 0x80.
Более старый механизм - это шлюз вызова ; первоначально использовался в Multics, а затем, например, см. шлюз вызова на Intel x86. Он позволяет программе вызывать функцию ядра напрямую, используя безопасный механизм передачи управления, который операционная система настраивает заранее. Этот подход был непопулярным на x86, предположительно из-за требования дальнего вызова (вызов процедуры, расположенной в другом сегменте, чем текущий сегмент кода), который использует сегментацию памяти x86 и, как следствие, отсутствие переносимости, которое она вызывает, а также наличие более быстрых инструкций, упомянутых выше.
Для архитектуры IA-64 EPC
используется инструкция (Enter Privileged Code). Первые восемь аргументов системного вызова передаются в регистры, а остальные передаются в стек.
В семействе мэйнфреймов IBM System / 360 и его преемниках инструкция Supervisor Call ( SVC) с номером в инструкции, а не в регистре, реализует системный вызов для устаревших средств в большинстве собственных операционных систем IBM, а также для все системные вызовы в Linux. В более поздних версиях MVS IBM использует инструкцию Program Call (PC) для многих новых возможностей. В частности, ПК используется, когда вызывающий абонент может находиться в режиме блокировки запроса на обслуживание (SRB).
PDP-11 миникомпьютер использовали EMT и IOT инструкции, которые, подобно IBM System / 360 SVC и x86 INT, поставить код в инструкции; они генерируют прерывания по определенным адресам, передавая управление операционной системе. VAX 32-битный преемник PDP-11 серии использовал ЧКИ, ЧМЭ и CHMS инструкцию, чтобы системные вызовы в привилегированную коду на различных уровнях; код является аргументом инструкции.
Системные вызовы можно условно разделить на шесть основных категорий:
fork
в Unix-подобных системах или NtCreateProcess
в Windows NT Native API )Системные вызовы в большинстве Unix-подобных систем обрабатываются в режиме ядра, что достигается изменением режима выполнения процессора на более привилегированный, но переключение контекста процесса не требуется - хотя переключение контекста привилегий действительно происходит. Аппаратное обеспечение видит мир с точки зрения режима выполнения в соответствии с регистром состояния процессора, а процессы - это абстракция, предоставляемая операционной системой. Системный вызов обычно не требует переключения контекста на другой процесс; вместо этого он обрабатывается в контексте того, какой процесс его вызвал.
В многопоточном процессе системные вызовы могут выполняться из нескольких потоков. Обработка таких вызовов зависит от конструкции конкретного ядра операционной системы и среды выполнения приложения. В следующем списке показаны типичные модели, за которыми следуют операционные системы: