Эта глава посвящена теории планирования процессов, а также алгоритмам и специфической реализации планировщика ядра Linux. В следующей главе будет рассмотрен основной интерфейс, который предоставляется ядром для выполняющихся процессов, — системные вызовы.
Глава 5
Системные вызовы
Ядро операционной системы предоставляет набор интерфейсов, благодаря которым процессы, работающие в пространстве пользователя, могут взаимодействовать с системой. Эти интерфейсы предоставляют пользовательским программам доступ к аппаратному обеспечению и другим ресурсам операционной системы. Интерфейсы работают как посыльные между прикладными программами и ядром, при этом пользовательские программы выдвигают различные запросы, а ядро выполняет их (или приказывает убираться подальше). Тот факт, что такие интерфейсы существуют, а также то, что прикладные программы не имеют права непосредственно делать все, что им заблагорассудится, является ключевым моментом для обеспечения стабильности системы, а также позволяет избежать крупных беспорядков.
Системные вызовы являются прослойкой между аппаратурой и процессами, работающими в пространстве пользователя. Эта прослойка служит для трех главных целей. Во-первых, она обеспечивает абстрактный интерфейс между аппаратурой и пространством пользователя. Например, при записи или чтении данных из файла прикладным программам нет дела до типа жесткого диска, до среды, носителя информации, и даже до типа файловой системы, на которой находится файл. Во-вторых, системные вызовы гарантируют безопасность и стабильность системы. Так как ядро работает посредником между ресурсами системы и пространством пользователя, оно может принимать решение о предоставлении доступа в соответствии с правами пользователей и другими критериями. Например, это позволяет предотвратить возможность неправильного использования аппаратных ресурсов программами, воровство каких-либо ресурсов у других программ, а также возможность нанесения вреда системе. И наконец, один общий слой между пространством пользователя и остальной системой позволяет осуществить виртуальное представление процессов, как обсуждается в главе 3, "Управление процессами".
Если бы приложения имели свободный доступ ко всем ресурсам системы без помощи ядра, то было бы почти невозможно реализовать многозадачность и виртуальную память. В операционной системе Linux системные вызовы являются единственным средством, благодаря которому пользовательские программы могут связываться с ядром; они являются единственной законной точкой входа в ядро. Другие интерфейсы ядра, такие как файлы устройств или файлы на файловой системе /proc
, в конечном счете сводятся к обращению через системные вызовы.
Интересно, что в ОС Linux реализовано значительно меньше системных вызовов, чем во многих других операционных системах[23].
В этой главе рассказывается о роли и реализации системных вызовов в операционной системе Linux.
API, POSIX и библиотека С
Обычно прикладные программы не разрабатываются с непосредственным использованием системных вызовов, при этом используются программные интерфейсы приложений (Application Programing Interface, API). Это является важным, так как в таком случае нет необходимости в корреляции между интерфейсами, которые используют приложения, и интерфейсами, которые предоставляет ядро. Различные API определяют набор программных интерфейсов, которые используются приложениями. Эти интерфейсы могут быть реализованы с помощью одного системного вызова, нескольких системных вызовов, а также вообще без использования системных вызовов. В действительности, может существовать один и тот же программный интерфейс приложений для различных операционных систем, в то время как реализация этих API может для разных ОС существенно отличаться.
Один из наиболее популярных программных интерфейсов приложений в мире Unix-подобных систем базируется на стандарте POSIX. Технически стандарт POSIX включает в себя набор стандартов IEEE[24], целью которого является обеспечение переносимого стандарта операционной системы, приблизительно базирующегося на ОС Unix. ОС Linux соответствует стандарту POSIX.
Стандарт POSIX является хорошим примером соотношения между интерфейсом API и системными вызовами. Для большинства Unix-подобных операционных систем вызовы интерфейса API, определенные в стандарте POSIX, сильно коррелируют с системными вызовами. Конечно, стандарт POSIX создавался для того, чтобы сделать те интерфейсы, которые предоставляли ранние версии ОС Unix, похожими между собой. С другой стороны, некоторые операционные системы, далекие от OS Unix, такие как Windows NT, предоставляют библиотеки, совместимые со стандартом POSIX.