Операционные системы
Операционные системы
- Слайды лекций. Часть 1. Часть 2. Часть 3. Часть 4.
- Видео лекций
- Вопросы к экзамену
Лабораторные работы (Продвинутый трек)
Задания на лабораторные работы (pdf)
- Задание 1. Введение в Xv6
- Задание 2. Аллокатор
- Задание 3. Copy-on-write fork
- Задание 4.1 Файловая система в Linux
- Задание 4.2 Диспетчер корутин
Дополнительные файлы
Задания 1-3: Модификация учебной ОС Xv6: указания к ЛР, исходники, тестовая система
- Репозиторий: https://github.com/secs-dev/xv6-riscv
- Архив: os-lab-advanced-1-2-3-xv6.zip
Задание 4.1: указания к ЛР, шаблон с модулем ядра "привет, мир"
- Репозиторий: https://github.com/secs-dev/os-course/tree/main/lab/vtfs
- Архив: os-lab-advanced-4-linux-fs.zip
Задание 4.2: шаблон проекта
- Репозиторий: https://github.com/vityaman-edu/coroed
- Архив: os-lab-advanced-4-fiber.zip
Лабораторные работы (Базовый трек)
Лабораторная работа №1
Задание Часть 1. Запуск программ
Необходимо реализовать собственную оболочку командной строки - shell. Выбор ОС для реализации производится на усмотрение студента. Shell должен предоставлять пользователю возможность запускать программы на компьютере с переданными аргументами командной строки и после завершения программы показывать реальное время ее работы (подсчитать самостоятельно как «время завершения» – «время запуска»).
Задание Часть 2. Мониторинг и профилирование
Разработать комплекс программ-нагрузчиков по варианту, заданному преподавателем. Каждый нагрузчик должен, как минимум, принимать параметр, который определяет количество повторений для алгоритма, указанного в задании. Программы должны нагружать вычислительную систему, дисковую подсистему или обе подсистемы сразу. Необходимо скомпилировать их без опций оптимизации компилятора.
Перед запуском нагрузчика, попробуйте оценить время работы вашей программы или ее результаты (если по варианту вам досталось измерение чего либо). Постарайтесь обосновать свои предположения. Предположение можно сделать, основываясь на свой опыт, знания ОС и характеристики используемого аппаратного обеспечения.
- Запустите программу-нагрузчик и зафиксируйте метрики ее работы с помощью инструментов для профилирования. Сравните полученные результаты с ожидаемыми. Постарайтесь найти объяснение наблюдаемому.
- Определите количество нагрузчиков, которое эффективно нагружает все ядра процессора на вашей системе. Как распределяются времена USER%, SYS%, WAIT%, а также реальное время выполнения нагрузчика, какое количество переключений контекста (вынужденных и невынужденных) происходит при этом?
- Увеличьте количество нагрузчиков вдвое, втрое, вчетверо. Как изменились времена, указанные на предыдущем шаге? Как ведет себя ваша система?
- Объедините программы-нагрузчики в одну, реализованную при помощи потоков выполнения, чтобы один нагрузчик эффективно нагружал все ядра вашей системы. Как изменились времена для того же объема вычислений? Запустите одну, две, три таких программы.
- Добавьте опции агрессивной оптимизации для компилятора. Как изменились времена? На сколько сократилось реальное время исполнения программы нагрузчика?
Ограничения
Программа (комплекс программ) должна быть реализован на языке C, C++.
Дочерние процессы должны быть созданы через заданные системные вызовы выбранной операционной системы, с обеспечением корректного запуска и и завершения процессов. Запрещено использовать высокоуровневые абстракции над системными вызовами. Необходимо использовать, в случае Unix, процедуры libc.
Требования к отчету и защите
- Отчет должен содержать титульный лист с указанием номера и названия ЛР, вашего ФИО, ФИО преподавателя практики, номера вашей группы, варианта ЛР.
- Отчет должен содержать текст задания в соответствии с вариантом.
- Отчет должен содержать листинг исходного кода всех программ, написанных в рамках данной ЛР.
- Отчет должен содержать предположения о свойствах программ-нагрузчиков
- Отчет должен содержать результаты измерений и метрик программ-нагрузчиков, полученных инструментами мониторинга. Должно быть описано, какие утилиты запускались, с какими параметрами и выводом.
- Отчет должен содержать сравнительный анализ ожидаемых и фактических значений.
- Отчет должен содержать вывод.
- Студент должен быть готов продемонстрировать работоспособность Shell и предоставить исходный код.
- Студент должен быть готов воспроизвести ход работы в рамках части 2 и продемонстрировать схожие результаты работы программ-нагрузчиков.
Темы для подготовки к защите лабораторной работы:
- Структура процесса и потоков;
- Системные утилиты сбора статистики ядра;
- Основы ввода-вывода (блочный и последовательный ввод-вывод);
- Файловая система procfs;
- Использование утилиты strace, ltrace, bpftrace;
- (*) Профилирование и построение flamegraph'а и stap;
Лабораторная работа №2
Задание
Для оптимизации работы с блочными устройствами в ОС существует кэш страниц с данными, которыми мы производим операции чтения и записи на диск. Такой кэш позволяет избежать высоких задержек при повторном доступе к данным, так как операция будет выполнена с данными в RAM, а не на диске (вспомним пирамиду памяти).
В данной лабораторной работе необходимо реализовать блочный кэш в пространстве пользователя в виде динамической библиотеки (dll или so). Политику вытеснения страниц и другие элементы задания необходимо получить у преподавателя.
При выполнении работы необходимо реализовать простой API для работы с файлами, предоставляющий пользователю следующие возможности:
- Открытие файла по заданному пути файла, доступного для чтения. Процедура возвращает некоторый хэндл на файл. Пример:
int lab2_open(const char *path).
- Закрытие файла по хэндлу. Пример:
int lab2_close(int fd).
- Чтение данных из файла. Пример:
ssize_t lab2_read(int fd, void buf[.count], size_t count).
- Запись данных в файл. Пример:
ssize_t lab2_write(int fd, const void buf[.count], size_t count).
- Перестановка позиции указателя на данные файла. Достаточно поддержать только абсолютные координаты. Пример:
off_t lab2_lseek(int fd, off_t offset, int whence).
- Синхронизация данных из кэша с диском. Пример:
int lab2_fsync(int fd).
Операции с диском разработанного блочного кеша должны производиться в обход page cache используемой ОС.
В рамках проверки работоспособности разработанного блочного кэша необходимо адаптировать указанную преподавателем программу-загрузчик из ЛР 1, добавив использование кэша. Запустите программу и убедитесь, что она корректно работает. Сравните производительность до и после.
Ограничения
- Программа (комплекс программ) должна быть реализован на языке C или C++.
- Если по выданному варианту задана политика вытеснения Optimal, то необходимо предоставить пользователю возможность подсказать page cache, когда будет совершен следующий доступ к данным. Это можно сделать либо добавив параметр в процедуры read и write (например, ssize_t lab2_read(int fd, void buf[.count], size_t count, access_hint_t hint)), либо добавив еще одну функцию в API (например, int lab2_advice(int fd, off_t offset, access_hint_t hint)). access_hint_t в данном случае – это абсолютное время или временной интервал, по которому разработанное API будет определять время последующего доступа к данным.
- Запрещено использовать высокоуровневые абстракции над системными вызовами. Необходимо использовать, в случае Unix, процедуры libc.
Требования к отчету и защите
Отчет должен содержать:
титульный лист с указанием номера и названия ЛР, вашего ФИО, ФИО преподавателя практики, номера вашей группы, варианта ЛР;
текст задания в соответствии с вариантом;
краткий обзор кода;
данные о работе программы-нагрузчика до и после внедрения своего page cache;
заключение с анализом результатов и выводом
Темы для подготовки
Файловые системы в Linux, структура файла, взаимодействие ФС и диска;
Файловая система ext4;
Page cache в ОС;
Политики вытеснения кэшей;
Динамические библиотеки в Linux;
Лабораторная работа №3
Разработать комплекс программ на пользовательском уровне и уровне ярда, который собирает информацию на стороне ядра и передает информацию на уровень пользователя, и выводит ее в удобном для чтения человеком виде. Программа на уровне пользователя получает на вход аргумент(ы) командной строки (не адрес!), позволяющие идентифицировать из системных таблиц необходимый путь до целевой структуры, осуществляет передачу на уровень ядра, получает информацию из данной структуры и распечатывает структуру в стандартный вывод. Загружаемый модуль ядра принимает запрос через указанный в задании интерфейс, определяет путь до целевой структуры по переданному запросу и возвращает результат на уровень пользователя.
Интерфейс передачи между программой пользователя и ядром и целевая структура задается преподавателем. Интерфейс передачи может быть один из следующих:
- syscall - интерфейс системных вызовов.
- ioctl - передача параметров через управляющий вызов к файлу/устройству.
- procfs - файловая система /proc, передача параметров через запись в файл.
- debugfs - отладочная файловая система /sys/kernel/debug, передача параметров через запись в файл.
Целевая структура может быть задана двумя способами:
- Именем структуры в заголовочных файлах Linux
- Файлом в каталоге /proc. В этом случае необходимо определить целевую структуру по пути файла в /proc и выводимым данным.