Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Акуленок_часть1.doc
Скачиваний:
38
Добавлен:
13.11.2019
Размер:
1.43 Mб
Скачать

3.7. Системные вызовы

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

Системные вызовы (systems calls) – это интерфейс между операционной системой и пользовательской программой. Они создают, удаляют и используют различные объекты, главные из которых – процессы и файлы. Пользовательская программа запрашивает сервис у операционной системы, осуществляя системный вызов. Имеются библиотеки процедур, которые загружают машинные регистры определенными параметрами и осуществляют прерывание процессора, после чего управление передается обработчику данного вызова, входящему в ядро операционной системы. Цель таких библиотек – сделать системный вызов похожим на обычный вызов подпрограммы.

Основное отличие состоит в том, что при системном вызове задача переходит в привилегированный режим или режим ядра (kernel mode). По­этому системные вызовы иногда еще называют программными прерыва­ниями, в отличие от аппаратных прерываний, которые чаще называют просто прерываниями.

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

Системные вызовы для управления просты, но эффективны. В их число входят следующие:

  1. fork() – создать процесс. Для создания нового процесса используется системный вызов fork(). В среде программирования нужно относиться к этому системному вызову как к вызову функции, возвращающей целое значение – идентификатор порожденного процесса, который затем может использоваться для управления (в ограниченном смысле) порожденным процессом. Реально, все процессы системы UNIX, кроме начального, запускаемого при раскрутке системы, образуются при помощи системного вызова fork().

Вот что делает ядро системы при выполнении системного вызова fork():

  • Выделяет память под описатель нового процесса в таблице описателей процессов.

  • Назначает уникальный идентификатор процесса (PID) для вновь образованного процесса.

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

  • Увеличивает счетчики открытия файлов (процесс–потомок автоматически наследует все открытые файлы своего родителя).

  • Возвращает вновь образованный идентификатор процесса в точку возврата из системного вызова в процессе–предке и возвращает значение 0 в точке возврата в процессе–потомке.

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

  2. exit() – завершить процесс. В системе UNIX процесс завершает свое выполнение, запуская системную функцию exit(). После этого процесс переходит в состояние "прекращения существования", освобождает ресурсы и ликвидирует свой контекст. Система не накладывает никакого ограничения на продолжительность выполнения процесса, и зачастую процессы существуют в течение довольно длительного времени. Нулевой процесс (программа подкачки) и процесс 1 (init), к примеру, существуют на протяжении всего времени жизни системы. Продолжительными процессами являются также getty–процессы, контролирующие работу терминальной линии, ожидая регистрации пользователей, и процессы общего назначения, выполняемые под руководством администратора.

  3. kill() – послать сигнал. Процессы могут сами посылать сигналы, используя системную функцию kill().

  4. signal()– задать реакцию на сигнал;

  5. wait() – ждать завершения процесса. Чтобы процесс–предок мог синхронизовать свое выполнение с выполнением своих процессов–потомков, существует системный вызов wait(). Выполнение этого системного вызова приводит к приостановке выполнения процесса до тех пор, пока не завершится выполнение какого–либо из процессов, являющихся его потомками. В качестве прямого параметра системного вызова wait() указывается адрес памяти (указатель), по которому должна быть возвращена информация, описывающая статус завершения очередного процесса–потомка, а ответным (возвратным) параметром является PID завершившегося процесса–потомка.