stringtranslate.com

Системный вызов

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

В вычислительной технике системный вызов (обычно сокращенно 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]

  1. Контроль над процессом
  2. Управление файлами
    • создать файл, удалить файл
    • открыто закрыто
    • читать, писать, перемещать
    • получить/установить атрибуты файла
  3. Управление устройствами
    • запросить устройство, освободить устройство
    • читать, писать, перемещать
    • получить/установить атрибуты устройства
    • логически подключать или отключать устройства
  4. Информационное обслуживание
    • получить/установить общую информацию о системе (включая время, дату, имя компьютера, предприятие и т. д.)
    • получить/установить метаданные процесса, файла или устройства (включая автора, начало, время и дату создания и т. д.)
  5. Коммуникация
    • создать, удалить соединение связи
    • отправлять, получать сообщения
    • информация о статусе передачи
    • подключать или отключать удаленные устройства
  6. Защита
    • получить/установить права доступа к файлу

Режим процессора и переключение контекста

Системные вызовы в большинстве Unix-подобных систем обрабатываются в режиме ядра , что достигается путем изменения режима выполнения процессора на более привилегированный, но переключение контекста процесса не требуется, хотя переключение контекста привилегий все же происходит. Аппаратное обеспечение видит мир с точки зрения режима выполнения в соответствии с регистром состояния процессора , а процессы — это абстракция, предоставляемая операционной системой. Системный вызов обычно не требует переключения контекста на другой процесс; вместо этого он обрабатывается в контексте того процесса, который его вызвал. [13] [14]

В многопоточном процессе системные вызовы могут выполняться из нескольких потоков . Обработка таких вызовов зависит от конструкции конкретного ядра операционной системы и среды выполнения приложения. В следующем списке показаны типичные модели, за которыми следуют операционные системы: [15] [16]

Смотрите также

Примечания

  1. ^ В UNIX-подобных операционных системах системные вызовы используются только для ядра.
  2. ^ Во многих, но не во всех случаях, IBM документировала, например, номер SVC, регистрируемый параметр.
  3. ^ Компоненты CP CP-67 и VM используют инструкцию диагностики (DIAG) в качестве вызова гипервизора (HVC) от виртуальной машины к CP.

Рекомендации

  1. ^ IBM (март 1967 г.). «Написание процедур SVC». Руководство программиста операционной системы IBM System/360 (PDF) . Третье издание. стр. 32–36. C28-6550-2.
  2. ^ «Системные вызовы (2) - страница руководства Linux» .
  3. ^ OpenBSD (14 сентября 2013 г.). «Имена системных вызовов (kern/syscalls.c)». Перекрестная ссылка BSD .
  4. ^ NetBSD (17 октября 2013 г.). «Имена системных вызовов (kern/syscalls.c)». Перекрестная ссылка BSD .
  5. ^ «FreeBSD syscalls.c, список имен и идентификаторов системных вызовов» .
  6. Матеуш "j00ru" Юрчик (5 ноября 2017 г.). «Таблица системных вызовов Windows WIN32K.SYS (NT/2000/XP/2003/Vista/2008/7/8/10)».{{cite web}}: CS1 maint: числовые имена: список авторов ( ссылка )
  7. ^ "План 9 sys.h, список имен и идентификаторов системных вызовов" .
  8. ^ "SYSENTER (вики OSDev)" .
  9. Аноним (19 декабря 2002 г.). «Linux 2.5 получает vsyscalls и поддержку sysenter». Ядерная ловушка . Проверено 1 января 2008 г.
  10. ^ Ману Гарг (2006). «Механизм системных вызовов на основе Sysenter в Linux 2.6».
  11. ^ «Освобождение: Справочник по набору инструкций x86» . renejeschke.de . Проверено 4 июля 2015 г.
  12. ^ Зильбершац, Авраам (2018). Концепции операционной системы . Питер Б. Гэлвин; Грег Ганье (10-е изд.). Хобокен, Нью-Джерси: Уайли. п. 67. ИСБН 9781119320913. ОСЛК  1004849022.
  13. ^ Бах, Морис Дж. (1986), Проектирование операционной системы UNIX , Prentice Hall, стр. 15–16.
  14. ^ Эллиот, Джон (2011). «Обсуждение реализации системных вызовов в ProgClub, включая цитату Баха 1986».
  15. ^ «Нити».
  16. ^ «Модели резьбы» (PDF) .

Внешние ссылки