Теоретические сведения
Кафедра «Информационная безопасность компьютерных систем»
ЛАБОРАТОРНАЯ РАБОТА №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 процесса;
|
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 восстанавливают ранее сохраненное состояние всех регистров процессора и передают управление процессору.