Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Компонентный состав операционных систем. Системные вызовы



Любая сложная система должна иметь понятную и рациональную структуру, то есть разделяться на модули, имеющие законченное функциональное назначение с четкими правилами взаимодействия. Функциональная сложность операционной системы неизбежно приводит к сложности ее архитектуры – структурной организации на основе различных программных модулей. Обычно в состав операционной системы входят: исполняемые и объектные модули, библиотеки, модули исходного текста программ, программные модули специального формата (загрузчик операционной системы, драйверы ввода-вывода), файлы конфигурации, файлы документации, модули справочной системы и пр. Большинство современных операционных систем представляют собой хорошо структурированные модульные системы, способные к развитию, расширению и переносу на новые платформы. Единой архитектуры операционных систем не существует, но существуют универсальные подходы к ее структурированию. Общим подходом к структуризации является разделение всех модулей на две группы:

1. Ядро – модули, выполняющие основные функции операционной системы: управление процессами, управление памятью, управление устройствами ввода-вывода и т.п. В состав ядра входят:

- функции, решающие внутрисистемные задачи организации вычислительного процесса: переключение контекстов, загрузка/выгрузка станиц, обработка прерываний;

- функции для поддержки приложений, создающие для них прикладную программную среду.

Приложения могут обращаться к ядру с запросами (системными вызовами) для выполнения конкретных действий, например, открытия и чтения файла, получения системного времени и т.д. Функции ядра, которые могут вызываться приложениями, образуют интерфейс прикладного программирования API. Функции ядра являются наиболее часто выполняемыми, поэтому скорость их выполнения определяет производительность всей системы. Для обеспечения высокой скорости работы операционной системы все модули ядра или большая их часть постоянно находятся в оперативной памяти, то есть являются резидентными. Обычно ядро оформляется в виде программного модуля специального формата, отличающегося от формата пользовательских приложений.

2. Модули, выполняющие вспомогательные функции операционной системы, например, программы архивирования данных, программы дефрагментации. Вспомогательные модули оформляются либо в виде приложений, либо в виде библиотек процедур. Так как некоторые компоненты операционной системы оформляются в виде приложений (т.е. в виде исполняемых модулей стандартного формата для операционной системы), то бывает сложно провести четкую грань между операционной системой и приложениями (рис.2.2.). Решение о том, является программа частью операционной системы или нет, принимает разработчик. Программа может существовать определенное время как пользовательское приложение, а потом стать частью операционной системы, или наоборот. Например, Web -браузер компании Microsoft сначала поставлялся как отдельное приложение, затем стал частью операционных систем семейства Windows.


 
 

Вспомогательные модули операционной системы обычно подразделяются на следующие группы:

- утилиты – программы, решающие отдельные задачи управления и сопровождения компьютерной системы, например, программы сжатия дисков, программы архивирования данных;

- системные обрабатывающие программы – текстовые или графические редакторы, компиляторы, компоновщики, отладчики;

- программы предоставления пользователю дополнительных услуг – специальный вариант пользовательского интерфейса, калькулятор, игры;

- библиотеки процедур, упрощающие разработку приложений: библиотека математических функций, функций ввода-вывода и т.д.

Как и обычные приложения, для выполнения своих задач утилиты, обрабатывающие программы и библиотеки операционной системы, обращаются к функциям ядра посредством системных вызовов (рис.2.3).

Модули операционной системы, оформленные в виде утилит, системных обрабатывающих программ и библиотек, обычно загружаются в оперативную память только на время выполнения своих функций, то есть являются транзитными. Постоянно в оперативной памяти располагаются только самые необходимые коды операционной системы, составляющие ее ядро. Такая организация операционной системы экономит оперативную память компьютера. Важным свойством архитектуры операционной системы, основанной на ядре, является возможность защиты кодов и данных операционной системы за счет выполнения функций ядра в привилегированном режиме. Разделение операционной системы на ядро и модули-приложения обеспечивает легкую расширяемость. Чтобы добавить новую высокоуровневую функцию, достаточно разработать новое приложение.

Компонентный состав операционной системы определяется набором функций, для выполнения которых она предназначена. Все программы, входящие в ее состав, можно разбить на две группы: управляющие программы и системные обрабатывающие программы (рис.2.4.).

 
 

1. Управляющая программа (микроядро операционной системы) – обязательный компонент, выполняющий следующие функции:

- планирование прохождения непрерывного потока заданий;

- управление распределением ресурсов;

- реализация принятых методов организации данных;

- управление операциями ввода-вывода;

- организация мультипрограммной работы;

- управление работоспособностью системы после сбоев.

2. Управление статическими ресурсами (заданиями) – ядро операционной системы осуществляет предварительное планирование потока заданий для выполнения и статическое распределение ресурсов между одновременно выполняемыми заданиями в процессе подготовки к выполнению (инициализации). К таким ресурсам относятся разделы памяти (оперативной, дисковой, внешней) и устройства, допускающие только монопольное использование. Данные ресурсы закрепляются за заданием или его частью с момента его инициализации до момента завершения. Такое управление называется мониторингом, а программы, его осуществляющие – мониторами.

3. Управление динамическими ресурсами (задачами) – ядро операционной системы осуществляет динамическое распределение ресурсов между несколькими задачами, решаемыми одновременно в мультипрограммном режиме для выполняемого потока заданий. Управление выполняет программа супервизор (планировщик).

4. Управление данными – ядро операционной системы обеспечивает все операции ввода-вывода (обмена между оперативной памятью и периферийными устройствами) на физическом и логическом уровнях. Например, организация необходимых информационных структур и таблиц, управление файловой системой и режимом прямого доступа к памяти, обработка ошибок ввода-вывода и т.д.

5. Управление восстановлением – ядро операционной системы регистрирует машинные сбои и отказы и восстанавливает работоспособность системы после их возникновения, если это возможно.

В качестве основных аппаратных ресурсов компьютера, подлежащих распределению, обычно рассматривают: время работы процессора; адресное пространство основной памяти; оборудование ввода-вывода; файлы, хранящиеся во внешней памяти. Основными подсистемами, обеспечивающими распределение указанных ресурсов операционной системы, являются:

- подсистема управления процессами (распределяет ресурс «процессорное время»);

- подсистема управления памятью (распределяет ресурс «адресное пространство основной памяти»);

- подсистема управления устройствами (распределяет ресурсы «оборудование ввода-вывода»;

- подсистема управления данными (распределяет ресурс «данные или файлы»).

Интерфейс между операционной системой и программами пользователя определяется набором системных вызовов, предоставляемых операционной системой. Концепция, лежащая в основе системных вызовов, практически одинакова для всех операционных систем. Механизм обращения к системным функциям является машинно-зависимым и часто реализуется на ассемблере, поэтому существуют библиотеки процедур, делающие возможным обращение к системным процедурам из программ написанных на языке С и др. Механизм действия системных вызовов можно рассмотреть на примере системного вызова read в UNIX (при использовании международного стандарта POSIX), который имеет три параметра:

- fd – параметр для задания файла;

- buffer – параметр, который указывает на буфер;

- nbytes – параметр, задающий количество байтов, которое нужно прочитать.

Как практически все системные вызовы, он запускается из программы, написанной на языке C с тем же именем, что и системный вызов read. Вызов из программы С:

count = read (fd, buffer, nbytes);

 
 

Системный вызов (и библиотечная процедура) возвращает количество прочитанных байтов в переменной count. Обычно это значение совпадает с параметром nbytes, но может быть и меньше, если, например, в процессе чтения процедуре встретился конец файла. Если системный вызов не может быть выполнен, значение счетчика count устанавливается равным 1 и номер ошибки помещается в глобальную переменную errno. Программа всегда должна проверять результат системного вызова, чтобы отслеживать появление ошибки.

Системные вызовы выполняются за серию шагов (рис. 2.5.). Вначале при подготовке к вызову библиотечной процедуры read, которая фактически осуществляется одноименным системным вызовом, вызывающая программа помещает параметры в стек (шаги 1-3). Компиляторы С и С++ помещают параметры в стек в обратном порядке. Первый и третий параметры передаются по значению, второй – по ссылке (передается адрес буфера, на что указывает символ &). Затем по команде процессора производится вызов библиотечной процедуры (шаг 4).

Библиотечная процедура обычно помещает номер системного вызова в то место, где его ожидает операционная система, например, регистр (шаг 5). Затем она выполняет команду TRAP (эмулированное прерывание) для переключения из пользовательского режима в режим ядра и начинает выполнение с фиксированного адреса внутри ядра (шаг 6). Запускаемая программа ядра проверяет номер системного вызова и отправляет его соответствующему обработчику, как правило, при использовании таблицы указателей на обработчики системных вызовов, индексированной по номерам вызовов (шаг 7). Далее запускается обработчик системных вызовов (шаг 8), по завершению работы которого управление передается в пространство пользователя к библиотечной процедуре – команде следующей за командой TRAP (шаг 9)[2]. Эта процедура передает управление программе пользователя обычным способом, которым производится возврат из вызванной процедуры (шаг 10).

Чтобы закончить работу, программа пользователя должна очистить стек (шаг 11), как это делается после каждого вызова процедуры. Последняя команда увеличивает указатель стека, таким образом, чтобы удалить параметры, помещенные в стек перед запросом read. Далее программа может продолжать свою работу.

В POSIX существует более 100 системных вызовов, точнее библиотечных процедур, которые выполняют эти вызовы. Некоторые из них, которые наиболее часто используются, приведены в таблице 2.1.

Таблица 2.1.

Системные вызовы стандарта POSIX

Вызов Описание
Управление процессами
Pid=fork() Создает дочерний процесс, идентичный родительскому
Pid=waitpid(pid, &statioc, options) Ожидает завершения дочернего процесса
s=execve(name, argv, environp) Перемещает образ памяти процесса
Exit(status) Завершает выполнение процесса и возвращает статус
Управление файлами
fd=open(file, how,...) Открывает файл для чтения, записи
s=close(fd) Закрывает открытый файл
n=read(fd, buffer, nbytes) Читает данные из файла в буфер
n=write(fd, buffer, nbytes) Пишет данные из буфера в файл
Position=lseek(fd, offset, whence) Передвигает указатель файла
s=stat(name, &buf) Получает информацию о состоянии файла
Управление каталогами и файловой системой
s=mkdir(name, mode) Создает новый каталог
s=rmdir(name) Удаляет пустой каталог
s=link(name1, name2) Создает новый элемент с именем
s=unlink(name) Удаляет элемент каталога
s=mount(special, name, flag) Монтирует файловую систему
s=umount(special) Демонтирует файловую систему
Разные
s=chdir(dimame) Изменяет рабочий каталог
s=chmod(name, mode) Изменяет биты защиты файла
s=kill(pid, signal) Посылает сигнал процессу
Seconds=time(&seconds) Получает время, прошедшее с 1 января 1970 года

Системный вызов fork (разветвление) является единственным способом создания нового процесса в UNIX. Он создает точную копию исходного процесса, включая дескрипторы файла, регистры и т.п. После вызова fork исходный процесс и его копия (родительский и дочерний) развиваются по отдельности друг от друга. Все переменные имеют одинаковые величины во время вызова fork, но как только родительские данные скопированы для создания дочернего процесса, последующие изменения в одном из них уже не влияют на другой.

В большинстве случаев после вызова fork дочернему процессу необходимо выполнить программный код, отличный от предназначенного для родительского процесса. Например, оболочка читает команды с терминала, запускает дочерний процесс, ждет, пока дочерний процесс выполнит команду и читает следующую команду после завершения работы дочернего процесса. Ожидая, пока дочерний процесс закончит работу, родительский процесс выполняет системный вызов waitpid, который ожидает завершения дочернего процесса (или всех дочерних процессов, если их на данный момент несколько). Для того чтобы Waitpid (pid, &statioc, options) ждал окончания дочернего процесса, задается первый параметр вызова равным -1. Когда waitpid выполнен, указатель, задаваемый вторым параметром, устанавливается на статус завершения дочернего процесса (нормальное или аварийное завершение и выходное значение). Третий параметр определяет различные необязательные настройки.

Когда печатается команда, оболочка создает дочерний процесс, который должен выполнить команду пользователя. Он делает это с помощью системного вызова execve (name, argv, environp), заменяющего его образ памяти файлом, названным в первом параметре. В общем случае у команды execve есть три параметра: имя файла, который будет выполняться, указатель на массив аргументов и указатель на массив переменных окружения. Различные библиотечные программы разрешают пропускать параметры или определять их другими способами.

При копировании файла из одного файла в другой (file1 в файл file 2) используется команда:

ср filel file2

После создания оболочкой дочернего процесса последний находит и исполняет файл ср и передает ему имена исходного и целевого файлов. Основной модуль программы ср содержит определение:

main (argc, argv, envp)

Параметр argc указывает количество записей в командной строке, включая имя программы. Параметр argv является указателем на массив указателей. Элемент i массива указывает на i -ю запись в командной строке. Параметр envp – указатель на массив строковых переменных окружения вида: имя=величина, которые используются для передачи программе информации типа терминала или имя каталога.

В UNIX под процессы отводится часть памяти, которая, в свою очередь, делится на три сегмента: текстовый (код программы), сегмент данных (переменные) и сегмент стека. Сегмент данных увеличивается снизу вверх, а стек увеличивается сверху вниз. Между ними находится часть неиспользованного адресного пространства. Стек автоматически занимает нужную ему часть участка памяти, но расширение сегмента данных выполняется явным образом. Для этого используется специальный системный вызов brk, задающий новый адрес для границы сегмента данных.

Многие системные вызовы имеют отношение к файловой системе. Чтобы прочитать или записать файл, его сначала нужно открыть при помощи вызова open (file, how,...). Для этого вызова указывается имя открываемого файла (задается абсолютный путь файла или ссылка на рабочий каталог) и код, означающий, что файл открывается для чтения, записи или того и другого. Возвращаемый дескриптор файла употребляется при чтении или записи. Файл закрывается с помощью вызова close, который делает дескриптор файла доступным при следующем открытии (open).

Несмотря на то, что большинство программ читает и записывает файлы с помощью последовательного доступа, некоторым прикладным программам необходима возможность доступа к любой, случайно выбранной части файла. Связанный с каждым файлом указатель содержит текущую позицию в файле. Когда чтение (запись) осуществляется последовательно, он обычно указывает на байт, который должен быть прочитан (записан) следующим. Вызов lseek (fd, offset, whence) может изменить значение позиции указателя, так что следующий вызов read или write начнет операцию в другой части файла. Первый параметр является идентификатором файла, второй – определяет позицию в файле, третий – указывает, является ли второй параметр позицией в файле относительно начала файла, относительно текущей позиции или относительно конца файла. Вызов lseek возвращает абсолютную позицию в файле после изменения указателя.

Для каждого файла UNIX хранит следующие данные: тип файла (обычный, специальный, каталог и пр.), размер, время последнего изменения и другую информацию. Программа может запросить эту информацию через системный вызов stat (name, &buf), первый параметр которого определяет требуемый файл, второй – указывает на структуру, куда нужно поместить информацию.

Вызовы mkdir и rmdir соответственно создают и удаляют пустые каталоги. Вызов link разрешает одному файлу появляться под двумя или более именами, часто в разных каталогах. Этот вызов обычно используется, когда несколько программистов, работающих в одной команде, должны совместно использовать один общий файл. Вызов mount позволяет объединять в одну две файловые системы. Например: на жестком диске находится корневая файловая система, содержащая исполняемые версии общих команд и наиболее часто используемые файлы. Пользователю нужно прочитать файлы с гибкого диска. При помощи системного вызова mount файловая система с гибкого диска присоединяется к корневой файловой системе, например:

mount ("/ dev / fdO ", "/ mnt ", 0);

Первый параметр определяет имя специального блочного файла на диске О, второй – место в дереве, куда будет вмонтирована файловая система, третий – указывает какая встроенная файловая система монтируется: для чтения и записи или только для чтения. После выполнения вызова mount доступ к файлу на диске О можно получить, указав его путь из корневого или рабочего каталога. Когда файловая система не нужна, ее демонтируют с помощью системного вызова umount.





Дата публикования: 2014-11-28; Прочитано: 1540 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.012 с)...