Главная страница Межпроцессное взаимодействие (состязание) вызов mknod, доступный только суперпользователю. Если же владельцем программы mkdir будет суперпользователь и для нее будут установлены права доступа 04755, обычные пользователи смогут запускать ее и тем самым вызывать mknod, но весьма ограниченным образом. Когда процесс исполняет файл, в разрешениях которого выставлены биты SETUID или SETGID, эффективный идентификатор пользователя или группы отличаются от настоящих значений. Но иногда для процесса важно знать, чему равны эффективные и реальные значения uid и gid. Чтобы получить эту информацию, процесс может делать системные вызовы getuid и getgid. Оба этих вызова возвращают одновременно и эффективный, и реальный идентификаторы, а чтобы получать эти значения по отдельности, служат четыре библиотечные процедуры: getuid, getgid, geteuid, getegid. Первые две возвращают реальные значения, вторые две - эффективные. Для обычных пользователей единственный способ изменить свой идентификатор - запустить программу, у которой установлен бит SETUID. Но для суперпользователей существует и другая возможность, предоставляемая системным вызовом setuid, устанавливающим одновременно реальное и эффективное значение uid. Вызов setgid, соответственно, устанавливает реальное и эффективное значение gid. Кроме того, суперпользователь может менять владельца файла при помощи системного вызова chown. Другими словами, у суперпольователя есть множество возможностей нарушать все возможные правила защиты. Это объясняет, почему многие студенты посвящают столь много времени попыткам стать суперпользователем. Два последних системных вызова из данной категории могут делаться и обычными процессами. Первый из них, umask, устанавливает системную битовую маску, применяемую для маскирования битов прав доступа к файлу при его создании. Если сделать вызов umask(022): то при вызовах creat или mknod в правах доступа к создаваемому объекту будут маскироваться биты 022. Иначе говоря, вызов creatCfile . 0777): создаст файл с правами доступа 0755, а не 0777. Кроме того, битовая маска наследуется дочерними процессами, поэтому, если оболочка сразу после входа сделает вызов umask, ни одна из запущенных пользователем в этой сессии программ не сможет создать файл, который может изменить другой пользователь. Когда владельцем программы является суперпользователь и у нее установлен бит SETUID, то она может обращаться к любому файлу. Но часто программе нужно знать, имеет ли вызвавший ее пользователь разрешение обращаться к данному файлу. Простая попытка обращения к файлу ничего не даст, так как она всегда завершится успехом. Следовательно, необходимо иметь возможность узнать, разрешен ли доступ для реального (а не эффективного) uid. Это можно сделать с помощью системного вызова access. Чтобы проверить возможность чтения, параметр mode должен быть равен 4, записи - 2 и исполнения - 1. Эти значения можно комбинировать. Например, если mode равен 6, то вызов вернет О, если разрешены и запись. и чтение. В противном случае вызов вернет -1. Если параметр mode равен О, то делается проверка того, что файл существует и возможен обзор ведущих к нему директорий. 1.4.6. Системные вызовы для работы со временем Для работы с часами у MINIX есть четыре системных вызова. Вызов time возвращает текущее время в секундах, причем нулем считается полночь 1 января 1970 года (имеется в виду начало дня, а не его конец). Кроме того, чтобы считывать значение системного таймера, нужно иметь возможность сначала это значение установить. Возможность установить часы дает вызов stime, доступный только суперпользователю. Третий вызов - utime, он позволяет владельцу файла изменить значение времени, записанное в i-узле файла. У этого вызова довольно офаниченная область применения, но некоторым профаммам он нужен, например, профамма touch устанавливает время в i-узле файла в соответствие с текущим значением времени. Наконец, есть вызов times, позволяющий узнать, сколько времени процессор провел, исполняя процесс, и сколько времени потрачено на систему (то есть на обработку системных вызовов). Кроме того, суммируется и возвращается общее время системы и процесса для всех дочерних процессов. 1.5. Структура операционной системы Теперь, когда мы уже видели, как выглядят операционные системы снаружи (то есть мы знакомы с профаммным интерфейсом), самое время заглянуть внутрь. Чтобы получить представление обо всем спектре возможных вариантов, в следующих разделах мы исследуем четыре различные использующиеся (или использовавшихся ранее) структуры. Исследование это нельзя назвать всесторонним, здесь лишь рассматриваются несколько моделей, применявшихся на практике в разных системах. Их четыре - монолитные системы, многоуровневые системы, виртуальные машины и модель клиент-сервер. 1.5.1. Монолитные системы в общем случае организация монолитной системы представляет собой большой беспорядок . То есть структура как таковая отсутствует. Операционная система написана в виде набора процедур, каждая из которых может вызывать другие, когда ей это нужно. При использовании такой техники каждая процедура системы имеет строго определенный интерфейс в терминах параметров и результатов, и каждая имеет возможность вызвать любую другую для выполнения некоторой необходимой для нее работы. Для построения монолитной системы необходимо скомпилировать все отдельные процедуры, а затем связать их в единый объектный файл с помощью компоновщика. Здесь, по существу, полностью отсутствует сокрытие деталей реализации - каждая процедура видит любую другую процедуру (в отличие от структуры, содержащей модули, в которых большая часть информации является локальной для модуля, и процедуры модуля можно вызвать только через специально определенные точки входа). Однако даже такие монолитные системы могут иметь некоторую структуру. При обращении к системным вызовам, поддерживаемым операционной системой, параметры помещаются в строго определенные места - регистры или стек, после чего выполняется специальная команда прерывания, известная как вызов ядра или вызов супервизора. Эта команда переключает машину из режима пользователя в режим ядра и передает управление операционной системе, что видно на шаге 1 рис. 1.12 (у большинства процессоров есть два режима работы: режим ядра, предназначенный для ОС, и пользовательский режим, в котором запрещен ввод/вывод и некоторые другие инструкции). Затем операционная система проверяет параметры вызова, чтобы определить, какой системный вызов должен быть выполнен (шаг 2). После этого операционная система обращается к таблице как к массиву с номером системного вызова в качестве индекса. В fe-м элементе таблицы содержится ссылка на процедуру обработки системного вызова k (шаг 3 на рис. 1.12). После того, как работа завершена, управление возвращается в пользовательскую программу, которая продолжит свою работу со следующего оператора (шаг 4). Пользовательская программа 1 Пользовательская программа 2 .Вызов ядра Процедура обработки системного вызова Табпица процедур Программы выполняются в режиме пользователя Операционная система работает в режиме ядра Рис. 1.12. Выполнение системного вызова: 1 - пользовательская программа вызывает прерывание; 2 - операционная система определяет номер процедуры обработчика; 3 - Операционная система вызывает обработчик; 4 - управление возвращается в основную программу Такая организация операционной системы предполагает следующую структуру: 1. Главная программа, которая вызывает требуемую служебную процедуру. 2. Набор служебных процедур, выполняющих системные вызовы. 3. Набор утилит, обслуживающих служебные процедуры. В этой модели для каждого системного вызова имеется одна служебная процедура. Утилиты выполняют функции, которые нужны нескольким служебным процедурам. Деление процедур на три уровня показано на рис. 1.13.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |