Теоретические сведения

Кафедра «Информационная безопасность компьютерных систем»

ЛАБОРАТОРНАЯ РАБОТА №5

СИСТЕМНЫЕ ВЫЗОВЫ

по дисциплине «Операционные системы»

Выполнил

студент гр. 2088/3 NOT_ME

Руководитель

Коноплев А.С.

Санкт-Петербург

Постановка задачи

1. Модифицировать текущий механизм обработки системных вызовов. Обработчик системных вызовов в userprog/syscall.c должен читать номер и аргументы системного вызова из стека и при завершении обработки возвращать значение пользовательской программе, изменяя содержимое регистра eax (необходимо будет использовать указатель стека из структуры intr_frame). Внести соответствующие изменения в функцию syscall_handler().

2. Реализовать набор системных вызовов. Для внедрения системных вызовов в первую очередь необходимо продумать способы, которыми будут осуществляться чтение и запись в виртуальное пространство пользователя (номер системного вызова и его аргументы находятся в пользовательском стеке). Номера системных вызовов определены в lib/syscall-nr.h. Каркасы функций расположены в lib/user/syscall.c.

Таблица 4.2. Системные вызовы ОС Pintos

Прототип системного вызова: Назначение:
void halt (void) Завершает работу ОС Pintos. Используйте функцию power_off(), которая определена в threads/init.h. Не используйте этот системный вызов из пользовательских программ.
void exit (int status) Завершает работу пользовательской программы, возвращая status ядру. Статус 0 означает безошибочное выполнение программы.
bool create (const char *file, unsigned initial_size) Создает новый файл с именем file и размером initial_size. Возвращает “true”, если файл успешно создан, и “false” в противном случае.
int open (const char *file)   Открывает файл с именем file. Возвращает целочисленное значение дескриптора файла fd или -1, если файл не может быть открыт. Дескрипторы 0 и 1 зарезервированы для стандартных потоков ввода-вывода: fd 0 - STDIN_FILENO, fd 1 - STDOUT_FILENO.
void close (int fd) Закрывает файл с дескриптором fd. При своем завершении процесс неявно закрывает все открытые файловые дескрипторы, словно вызывает функцию close для каждого из них.
int read (int fd, void *buffer, unsigned size)   Читает size байт из файла с дескриптором fd в буфер. Возвращает число считанных байт или -1, если файл не может быть прочитан. fd 0 выполняет чтение с клавиатуры с помощью функции input_getc() , определенной в devices/input.h.
int write (int fd, const void *buffer, unsigned size) Записывает size байт в файл с дескриптором fd. Возвращает число записанных байт или -1, если запись в файл невозможна. Запись в файл после EOF должна увеличивать размер файла, но в текущей реализации файловой системы Pintos такой механизм не предусмотрен. Система ожидает от пользователя запись в пределах заданного при создании размера файла. Если fd = 1, то система должна выполнять вывод на консоль. Используйте функцию putbuf(), определенную в lib/kernel/stdio.h и lib/kernel/console.c.
int wait (pid_t pid) Ожидает, пока дочерний процесс с идентификатором pid не завершит выполнение, затем возвращает код (статус) завершения дочернего процесса. Если дочерний процесс не вызвал функцию exit(), но был завершен ядром, то системный вызов wait(pid) должен возвращать значение -1. Системный вызов также должен возвращать -1 в следующих случаях: · pid не является дочерним процессом выполняющего системный вызов wait процесса;
  • системный вызов wait над pid уже был выполнен;
Процесс может порождать несколько дочерних процессов, выполнять системный вызов wait для них в любом порядке и даже завершать свое выполнение, не дождавшись завершения своих дочерних процессов. Перед тем, как приступить к внедрению системного вызова, нужно реализовать функцию process_wait() в userprog/process.c, и на ее основе выполнять системный вызов.
pid_t exec (const char *cmd_line) Запускает исполняемый файл, имя которого задано в cmd_line (с учетом всех аргументов) и возвращает уникальный идентификатор нового пользовательского процесса, который создается в результате запуска исполняемого файла. Системный вызов должен возвращать значение -1, если программа не может быть запущена.


Теоретические сведения

Системные вызовы обеспечивают взаимосвязь между ядром и программами пользователя.

Базовая реализация системных вызовов в ОС Pintos размещает аргументы с соответствующим номером системного вызова в регистры и вызывает прерывание 0x30. Это прерывание заставляет процессор остановить выполнение текущего задания, переключиться из режима пользователя в режим ядра и перейти к обработчику прерываний syscall_handler, который определен в userprog/syscall.c.

Прерывания служат для оповещения ядра системы о наступлении некоторого события. Многие механизмы операционной системы так или иначе взаимодействуют с прерываниями. В ОС Pintos прерывания можно разделить на две большие группы:

· Внутренние прерывания, т.е. прерывания, вызванные событиями в самом процессоре. Такими событиями могут быть системные вызовы, ошибки обращения по недопустимым адресам или деления на ноль. Так как внутренние прерывания вызваны процессором, они являются синхронными или синхронизированными с инструкциями процессора. Функция intr_disable() не осуществляет отключение внутренних прерываний.

  • Внешние прерывания, т.е. прерывания, источники которых расположены вне CPU. Такие прерывания поступают от периферийных устройств, таких как системный таймер, клавиатура, диски. Внешние прерывания являются асинхронными, их поступление никак не синхронизировано с выполнением команд. Обработка внешних прерываний может быть отключена функцией intr_disable().

В threads/interrupt.h и threads/interrupt.с расположены основные структуры и функции обработки прерываний. Основная работа функции intr_handler() заключается в вызове функции, предназначенной для обработки конкретного прерывания. Если такой функции не существует, intr_handler() завершается ошибкой и выводит информацию на консоль. Когда intr_handler() возвращает значение, ассемблерные функции в threads/intr-stubs.S восстанавливают ранее сохраненное состояние всех регистров процессора и передают управление процессору.

Наши рекомендации