Главная страница
Навигация по странице:

  • ЛАБОРАТОРНАЯ РАБОТА № 1 «Системный таймер

  • Цель работы. Изучение системы управления процессами и механизма работы системного таймера в ОС Pintos, анализ его недостатков и модификация его алгоритма.Задачи.

  • Дополнительные задания.

  • Отчёт 1. Лабораторная работа 1 Системный таймер по дисциплине Операционные системы


    Скачать 409.05 Kb.
    НазваниеЛабораторная работа 1 Системный таймер по дисциплине Операционные системы
    Дата22.09.2022
    Размер409.05 Kb.
    Формат файлаdocx
    Имя файлаОтчёт 1.docx
    ТипЛабораторная работа
    #691515

    1. Министерство образования и науки Российской Федерации

    2. Санкт-Петербургский Политехнический Университет Петра Великого



    3. Институт кибербезопасности и защиты информации

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

    1. «Системный таймер»



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



    1. Выполнил:

    2. студент гр. 4851001/90002 Судаков Д.И.

    <подпись>





    1. Ассистент: Крундышев В.М.

    <подпись>







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

    2. 2020

    Цель работы.

    Изучение системы управления процессами и механизма работы системного таймера в ОС Pintos, анализ его недостатков и модификация его алгоритма.

    Задачи.

    1) Составить таблицу функций системного таймера.

    2) Изобразить блок-схему текущего алгоритма работы функции timer_sleep() системного таймера в ОС Pintos.

    3) Разработать новый алгоритм работы системного таймера, который позволит избежать активного ожидания.

    4) Изобразить блок-схему реализованного алгоритма.

    5) Оценить решение, используя встроенную систему тестирования, предоставить результаты тестов.

    6) Выполнить индивидуальные задания и ответить на контрольные вопросы.

    Ход работы.

    1. Функции системного таймера



    Функция

    Назначение


    void

    timer_init(void)

    Устанавливает таймер на прерывание TIMER_FREQ раз в секунду, регистрирует прерывание


    void

    timer_calibrate(void)

    Оптимально калибрует переменную loops_per_tick, используемую для реализации кратких задержек


    int64_t

    timer_elapsed(int64_t then)

    Возвращает число тактов таймера, прошедших с момента THEN (значение, возвращенное функцией timer_ticks())


    void

    timer_ticks(void)

    Возвращает число тактов таймера с момента запуска операционной системы


    void

    timer_sleep(int64_t ticks)

    Переводит текущий поток в состояние BLOCKED примерно на TICKS тактов таймера. Прерывания должны быть включены


    void

    timer_msleep(int64_t ms)

    Переводит текущий поток в состояние BLOCKED примерно на ms миллисекунд. Прерывания должны быть включены


    void

    timer_usleep(int64_t us)

    Переводит текущий поток в состояние BLOCKED примерно на us микросекунд. Прерывания должны быть включены


    void

    timer_nsleep(int64_t ns)

    Переводит текущий поток в состояние BLOCKED примерно на ns наносекунд. Прерывания должны быть включены


    void

    timer_mdelay(int64_t ms)

    Ожидание примерно ms миллисекунд. Прерывания должны быть включены


    void

    timer_udelay(int64_t us)

    Ожидание примерно us микросекунд. Прерывания должны быть включены


    void

    timer_ndelay(int64_t ns)

    Ожидание примерно ns наносекунд. Прерывания должны быть включены


    void

    timer_print_stats(void)

    Выводит в консоль состояние таймера

    static void

    timer_interrupt(struct intr_frame *args UNUSED)

    Обработчик прерываний таймера

    static bool

    too_many_loops(unsigned loops)

    Возвращает true, если LOOPS итераций ожидают больше одного такта таймера, иначе возвращает false

    static void

    real_time_sleep(int64_t num, int32_t denom)

    Переводит текущий поток в состояние BLOCKED примерно на NUM/DENOM секунд

    static void

    real_time_delay(int64_t num, int32_t denom)

    Переводит текущий поток в состояние ожидания примерно на NUM/DENOM секунд

    static bool

    too_many_loops(unsigned loops)

    Проходит элементарный цикл LOOPS раз для реализации реальной задержки


    Табл. 1 – Функции системного таймера

    1. Блок-схема изначального алгоритма функции timer_sleep(int64_t ticks)

    Рис.1 – Схема изначального алгоритма функции timer_sleep(int64_t ticks)

    3) Для реализации нового алгоритма в код были внесены следующие изменения:

    1. В структуру thread в файле thread.h было добавлено поле int64_t awake_time, в которое записывается время в тактах с момента запуска ОС, когда процесс должен пробудиться.

    2. В файле timer.h был добавлен массив ссылок на структуры типа struct thread*, в файле timer.c была добавлена глобальная переменная counter, используемая для итерации по массиву.

    3. В файле timer.c была реализована функция add_thread(struct thread*), вызываемая в timer_sleep. Добавляет поток cur_thread в массив заблокированных потоков и затем сортирует этот массив.

    4. В timer.c была создана функция unblock(void), вызываемая в timer_interrupt на каждый тик таймера. Данная функция проходит по массиву, пробуждая потоки и удаляя их оттуда до тех пор, пока не встретит поток, время пробуждения которого еще не настало.

    1. Блок-схема разработанного алгоритма

    t
    imer_sleep timer_interrupt
    Рис. 2 – Блок-схема разработанного алгоритма

    1. Результаты тестов




    Рис.3 – Результат выполнения теста alarm-single

    Рис.4 – Результат выполнения теста alarm-multiple

    Рис.5 – Результат выполнения теста alarm-simultaneous



    Рис.6 – Результат выполнения теста alarm-negative



    Рис.7 -Результат выполнения теста alarm-zero

    Дополнительные задания.

    Max-rec-calls

    1. Задачи:

    1. Реализовать тест “max-rec-calls” в файле max-rec-calls.c

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

    3. Выяснить как и почему изменится количество максимально возможных вызовов, если в struct thread изменить name[16] на name[128].




    1. Ход выполнения задания

    1. В файле max-rec-calls.c была объявлена структура struct X, состоящая из двух полей int A и long int B, инициализация переменной типа struct X происходит в основной функции теста, там же под эту переменную выделяется память с помощью функции calloc(), также эта структура подается в качестве аргумента aux для thread_create().

    2. В файле max-rec-calls были объявлены функции void_func2(struct X *t) и void_func(int i, long int j). Вторая из них соответственно – это функция процесса двух переменных. Первая – функция, которая подается в качестве аргумента для thread_create() и вызывает вторую.

    3. В структуре struct thread в файле thread.h поле name[16] было изменено на name[128]. Изменения работы алгоритма после внесенных коррективов описаны в результатах.



    1. Результаты

    1. Скрины вывода результатов в консоль

    Рис.8 – Результат выполнения теста max-rec-calls до изменения поля name

    Рис. 9 – Результат выполнения теста max-rec-calls после изменения поля name

    1. Описание результатов

    Судя по полученным результатам, исходная версия ОС pintos позволяет осуществить примерно 103 рекурсивных вызова функции процесса. Такое значение объясняется тем, что процесс – это экземпляр программы во время выполнения, независимый объект, которому выделены системные ресурсы, эти ресурсы, в частности память, ограничены и используются при исполнении процесса в том числе при рекурсивных вызовах. Когда объем используемой памяти становится большим, чем это предусмотрено операционной системой, выполнение процесса экстренно прерывается и в терминал подается сообщение типа KERNEL PANIC, что и показано на рисунках 8 и 9. Также как показано на рисунках, изменение поля структуры struct thread name[16] на name[128] приводит к уменьшению максимального числа рекурсивных вызовов. До изменения это число было 103, а после оно стало равным 100.
    threads-pause-resume

    1. Задачи

    1. В файле thread.c реализовать функции thread_pause(tid_t t) – безусловная приостановка потока и thread_resume(tid_t t) – возобновление выполнения потока, ранее приостановленного с помощью thread_pause.

    2. В файле threads-pause-resume.c реализовать тест threads-pause-resume, демонстрирующий использование вышеописанных функций

    3. Объяснить полученные результаты

    1. Ход выполнения задания

    1. В файле thread.c были объявлены и описаны функции thread_pause(tid_t) и thread_resume(tid_t), получаемый аргумент они используют для нахождения процесса, который необходимо приостановить. Поиск осуществляется с помощью прохода по списку всех существующих процессов struct list all_list. В функции thread_pause(tid_t t) найденный элемент(процесс) переводится в состояние BLOCKED до того момента пока он не будет разблокирован функцией thread_resume(tid_t t).

    2. В файле threads-pause-resume.c в основной функции теста были созданы два процесса с помощью функции thread_create(…), а также в данном файле были объявлены и описаны функции, исполняемые этими процессами и бесконечно распечатывающие каждую секунду своё имя. Далее в основной функции теста на 4 секунды усыпляется main, после чего вызывается функция thread_pause(tid_t t), затем процесс main усыпляется еще на 4 секунды и вызывается функция thread_resume(tid_t t), и наконец, main снова усыпляется на 4 секунды, потом программа завершает работу.




    1. Результаты

    1. Скрин полученных результатов

    Рис.10 – Результат выполнения теста threads-pause-resume

    1. Описание результатов

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


    Вывод.

    Я изучил систему управления процессами и механизм работы системного таймера OC Pintos. Была выявлена ненадежность и нерациональность работы функции timer_sleep(int64_t ticks) в исходной версии ОС pintos. Данные недостатки был исправлен путем изменения алгоритма этой функции. В реализованном алгоритме функция thread_yield(void) больше не используется, вместо неё с помощью массива заблокированных процессов и функции проверки времени пробуждения процессы правильно погружаются в сон и пробуждаются через необходимое количество тактов. Помимо прочего, были выполнены дополнительные задания под номерами 2 и 7, полное описание выполнения которых указано в работе.


    написать администратору сайта