В вычислительной технике системный вызов (обычно сокращенно syscall ) — это программный способ, которым компьютерная программа запрашивает услугу у операционной системы [a] , в которой она выполняется. Сюда могут входить службы, связанные с аппаратным обеспечением (например, доступ к жесткому диску или доступ к камере устройства), создание и выполнение новых процессов , а также связь со встроенными службами ядра , такими как планирование процессов . Системные вызовы обеспечивают необходимый интерфейс между процессом и операционной системой.
В большинстве систем системные вызовы могут выполняться только из процессов пользовательского пространства , тогда как в некоторых системах, например OS/360 и последующих версиях , привилегированный системный код также выполняет системные вызовы. [1]
Для встроенных систем системный вызов обычно не меняет привилегированный режим ЦП.
Архитектура большинства современных процессоров, за исключением некоторых встраиваемых систем, предполагает модель безопасности . Например, модель колец определяет несколько уровней привилегий, с которыми может выполняться программное обеспечение: программа обычно ограничена своим собственным адресным пространством , так что она не может получить доступ или изменить другие запущенные программы или саму операционную систему, и обычно ей не разрешается напрямую манипулировать аппаратные устройства (например, буфер кадров или сетевые устройства).
Однако многим приложениям необходим доступ к этим компонентам, поэтому операционная система предоставляет системные вызовы для обеспечения четко определенных и безопасных реализаций таких операций. Операционная система работает на самом высоком уровне привилегий и позволяет приложениям запрашивать службы через системные вызовы, которые часто инициируются через прерывания . Прерывание автоматически переводит ЦП на некоторый повышенный уровень привилегий, а затем передает управление ядру, которое определяет, следует ли предоставить вызывающей программе запрошенную услугу. Если услуга предоставлена, ядро выполняет определенный набор инструкций, над которыми вызывающая программа не имеет прямого контроля, возвращает уровень привилегий вызывающей программе, а затем возвращает управление вызывающей программе.
Как правило, системы предоставляют библиотеку или API , который находится между обычными программами и операционной системой. В Unix-подобных системах этот API обычно является частью реализации библиотеки C (libc), такой как glibc , которая предоставляет функции-оболочки для системных вызовов, часто называемых так же, как системные вызовы, которые они вызывают. В Windows NT этот API является частью Native API в библиотеке ntdll.dll ; это недокументированный API, используемый реализациями обычного API Windows и напрямую используемый некоторыми системными программами в Windows. Функции-оболочки библиотеки предоставляют обычное соглашение о вызове функций ( вызов подпрограммы на уровне сборки ) для использования системного вызова, а также делают системный вызов более модульным . Здесь основной функцией оболочки является размещение всех аргументов, передаваемых системному вызову, в соответствующие регистры процессора (а, возможно, и в стек вызовов ), а также установка уникального номера системного вызова для вызова ядра. . Таким образом, библиотека, существующая между ОС и приложением, повышает переносимость .
Вызов библиотечной функции сам по себе не вызывает переключения в режим ядра и обычно представляет собой обычный вызов подпрограммы (с использованием, например, ассемблерной инструкции «CALL» в некоторых архитектурах набора инструкций (ISA)). Фактический системный вызов передает управление ядру (и в большей степени зависит от реализации и платформы, чем абстрагирующий его библиотечный вызов). Например, в Unix-подобных системах fork
и execve
— это функции библиотеки C, которые, в свою очередь, выполняют инструкции, вызывающие системные вызовы fork
и exec
. Выполнение системного вызова непосредственно в коде приложения более сложно и может потребовать использования встроенного ассемблерного кода (в C и C++ ), а также знания низкоуровневого двоичного интерфейса для операции системного вызова, что может быть предметом изменяться со временем и, таким образом, не быть частью двоичного интерфейса приложения ; библиотечные функции предназначены для абстрагирования этого.
В системах на основе экзоядра библиотека особенно важна как посредник. В экзоядрах библиотеки защищают пользовательские приложения от API ядра очень низкого уровня и обеспечивают абстракции и управление ресурсами .
IBM OS/360 , DOS/360 и TSS/360 реализуют большинство системных вызовов через библиотеку макросов языка ассемблера , [b] хотя есть несколько сервисов со связью вызовов. Это отражает их происхождение в то время, когда программирование на языке ассемблера было более распространенным, чем использование языка высокого уровня . Таким образом, системные вызовы IBM не могли напрямую выполняться программами на языке высокого уровня, но требовали вызываемой подпрограммы-оболочки языка ассемблера. С тех пор IBM добавила множество сервисов, которые можно вызывать из языков высокого уровня, например, в z/OS и z/VSE . В более позднем выпуске MVS/SP и во всех более поздних версиях MVS некоторые макросы системных вызовов генерируют вызов программы (PC).
В Unix , Unix-подобных и других POSIX- совместимых операционных системах популярными системными вызовами являются open
, read
, write
, close
, wait
, exec
, fork
, exit
и kill
. Многие современные операционные системы имеют сотни системных вызовов. Например, Linux и OpenBSD имеют более 300 различных вызовов, [2] [3] NetBSD — около 500, [4] FreeBSD — более 500, [5] Windows — около 2000, разделенных на win32k (графический) и ntdll. (основные) системные вызовы [6] , тогда как в Plan 9 их 51. [7]
Такие инструменты, как strace , ftrace и truss , позволяют процессу выполняться с самого начала и сообщать обо всех системных вызовах, которые вызывает процесс, или могут подключаться к уже запущенному процессу и перехватывать любой системный вызов, выполненный указанным процессом, если операция не нарушает разрешения. пользователя. Эта особая способность программы обычно также реализуется с помощью системных вызовов, таких как ptrace или системных вызовов файлов в procfs .
Реализация системных вызовов требует передачи управления из пространства пользователя в пространство ядра, что включает в себя некоторую особенность, специфичную для архитектуры. Типичный способ реализовать это — использовать программное прерывание или ловушку . Прерывания передают управление ядру операционной системы , поэтому программному обеспечению просто необходимо настроить некоторый регистр с необходимым номером системного вызова и выполнить программное прерывание.
Это единственный метод, предусмотренный для многих процессоров RISC , но архитектуры CISC , такие как x86, поддерживают дополнительные методы. Например, набор инструкций x86 содержит инструкции SYSCALL
/ SYSRET
и SYSENTER
/ SYSEXIT
(эти два механизма были независимо созданы AMD и Intel соответственно, но по сути они делают одно и то же). Это «быстрые» инструкции передачи управления, которые предназначены для быстрой передачи управления ядру для системного вызова без затрат на прерывание. [8] Linux 2.5 начал использовать это на x86 , где это возможно; раньше использовалась INT
инструкция, в которой номер системного вызова помещался в EAX
регистр перед выполнением прерывания 0x80. [9] [10]
Более старый механизм — это шлюз вызова ; первоначально использовался в Multics и позже, например, см. шлюз вызова на Intel x86 . Это позволяет программе напрямую вызывать функцию ядра, используя безопасный механизм передачи управления, который операционная система устанавливает заранее. Этот подход был непопулярен на x86, предположительно из-за требования дальнего вызова (вызов процедуры, расположенной в сегменте, отличном от текущего сегмента кода [11] ), который использует сегментацию памяти x86 и, как следствие, отсутствие переносимости , которое это вызывает. и существование более быстрых инструкций, упомянутых выше.
Для архитектуры IA-64EPC
используется команда (Введите привилегированный код). Первые восемь аргументов системного вызова передаются в регистрах, а остальные — в стеке.
В семействе мэйнфреймов IBM System/360 и его преемниках инструкция Supervisor Call ( SVC ) с номером в инструкции, а не в регистре, реализует системный вызов для устаревших средств в большинстве [c] собственных операционных систем IBM. и для всех системных вызовов в Linux. В более поздних версиях MVS IBM использует инструкцию Program Call (PC) для многих новых средств. В частности, ПК используется, когда вызывающий абонент может находиться в режиме блокировки запроса на обслуживание (SRB).
Миникомпьютер PDP-11 использовал инструкции EMT , TRAP и IOT , которые, подобно IBM System/360 SVC и x86 INT , помещали код в инструкцию; они генерируют прерывания по определенным адресам, передавая управление операционной системе. 32-битный преемник серии PDP-11 VAX использовал инструкции CHMK , CHME и CHMS для выполнения системных вызовов привилегированного кода на различных уровнях; код является аргументом инструкции.
Системные вызовы можно условно сгруппировать в шесть основных категорий: [12]
fork
в Unix-подобных системах или NtCreateProcess
в Windows NT Native API )Системные вызовы в большинстве Unix-подобных систем обрабатываются в режиме ядра , что достигается путем изменения режима выполнения процессора на более привилегированный, но переключение контекста процесса не требуется, хотя переключение контекста привилегий все же происходит. Аппаратное обеспечение видит мир с точки зрения режима выполнения в соответствии с регистром состояния процессора , а процессы — это абстракция, предоставляемая операционной системой. Системный вызов обычно не требует переключения контекста на другой процесс; вместо этого он обрабатывается в контексте того процесса, который его вызвал. [13] [14]
В многопоточном процессе системные вызовы могут выполняться из нескольких потоков . Обработка таких вызовов зависит от конструкции конкретного ядра операционной системы и среды выполнения приложения. В следующем списке показаны типичные модели, за которыми следуют операционные системы: [15] [16]
{{cite web}}
: CS1 maint: числовые имена: список авторов ( ссылка )