Практические работы

Учебный курс «Операционные системы»

Мониторы

Много подсказок

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

Безопасная обработка сетевых подключений и сигналов

Много подсказок

Требуется подготовить безопасную реализацию серверного процесса, который совмещает обработку соединений TCP/IP с обработкой сигналов (можно выбрать, скажем, сигнал SIGHUP). Приложение должно:

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

Фактически, работа сводится к правильному вызову функции pselect(), но все действия должны быть выполнены в предельно безопасном виде, исключающем любые race condition.

Модуль ядра Linux

Часть первая

Требуется подготовить модуль для загрузки в ядро Linux. Модуль должен:

  • сопровождаться Makefile для сборки;
  • оформляться в виде файла *.ko;
  • загружаться командой insmod и выгружаться командой rmmod;
  • при загрузке выводить в dmesg строку «Welcome to the Tomsk State University»;
  • при выгрузке выводить в dmesg строку «Tomsk State University forever!».

Часть вторая

Модуль, подготовленный на первой части работы, следует дополнить функционалом, который позволял бы при своей загрузке создавать файл tsulab в каталоге /proc. Содержимое этого файла будет определяться индивидуальным заданием для каждого учащегося, которое он будет получать при сдаче первой части работы.

Длинные работы в workqueue ядра Linux

Требуется подготовить модуль ядра Linux, выполняющий длительные работы посредством механизма workqueue. Работа не должна выполняться в контексте системного вызова загрузки модуля, обработчика таймера или обработчика прерывания. После загрузки модуля должна создаваться собственная очередь работ. Параметры очереди и количество одновременно выполняемых работ должны определяться программой. При загрузке модуля необходимо поставить в очередь несколько работ.

Каждая работа должна состоять из серии последовательных этапов. Продолжительность каждого этапа должна составлять не менее одной секунды. Во время выполнения каждого этапа работа должна сообщать в журнал ядра свой идентификатор, номер этапа и общее количество этапов. Для имитации длительной операции следует использовать ожидание, допускающее засыпание потока, например msleep() или schedule_timeout_interruptible(). Запрещено имитировать длительную работу циклом, полностью занимающим процессор.

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

После выгрузки модуля в журнал ядра должна быть выведена информация о завершении или отмене всех работ. Модуль не должен оставлять после себя созданные очереди, таймеры, файлы или другие объекты ядра.

Трассировка событий ядра с помощью eBPF

Требуется подготовить программу наблюдения за событиями ядра Linux с использованием eBPF. Программа должна состоять из части, выполняющейся в ядре, и пользовательской части, принимающей и отображающей события. В качестве события необходимо отслеживать запуск процессов, открытие файлов или выполнение системных вызовов. Конкретный тип события выбирается индивидуальным заданием.

Для каждого события необходимо передавать в пользовательскую программу:

  • идентификатор процесса;
  • идентификатор потока;
  • имя процесса;
  • идентификатор пользователя; *- время возникновения события;
  • дополнительные данные, зависящие от варианта.

Поток событий необходимо передавать через ring buffer или perf buffer. Активные события должны фильтроваться в ядре. Например, пользователь должен иметь возможность наблюдать только процессы с заданным идентификатором, пользователя или именем программы.

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