Дедлайн — 23 сентября 2020 года.
К этому моменту необходимо сделать pull request и пройти очное ревью. Если вы не успеете, каждую неделю вы будете терять 10% от стоимости задания, но не более 50% в сумме. Если у вас есть уважительная причина пропусков практических занятий, обсудите её с преподавателем для восстановления баллов и справедливости.
В этом семестре вы получите пять домашних заданий. Мы будем постепенно дорабатывать и улучшать операционную систему xv6 — учебную ОС, разрабатываемую с 2006 года в MIT. Для выполнения следующих заданий нам понадобится немного понимать, как работает эта ОС и уметь её собирать.
Наша цель — познакомиться с операционной системой xv6 и подготовить окружение для работы.
Более подробно разобраться с xv6 поможет книга R. Cox, F. Kaashoek, R. Morris «xv6: a simple, Unix-like teaching operating system» (на английском).
Задания этого курса можно выполнять как на Mac OS, так и на Linux. Выберите нужную инструкцию:
Если вы пользуетесь Windows, то мне вас жаль. Мы предлагаем несколько способов решения этой проблемы:
-
Поставьте операционную систему на базе ядра Linux. Её можно поставить как вместо Windows, так и рядом с ней, если у вас на диске достаточно места. Например, попробуйте Ubuntu.
-
Скачайте менеджер виртуальных машин VirtualBox и создайте ВМ с Linux там.
-
Попробуйте поднять всё в Linux Subsystem for Windows (мы не проверяли этот способ, не гарантируем его работу и не помогаем с ним).
-
Попробуйте воспользоваться Windows-версиями GCC и QEMU, чтобы собрать все необходимые инструменты, и запустить всё прямо на Windows (мы не проверяли этот способ, не гарантируем его работу и не помогаем с ним).
Если вы разберётесь с этим способом и будете готовы написать инструкцию для остальных студентов, то вы получите 5 бонусных баллов. Этот бонус можно сложить с подзаданием 5.
Склонируйте этот репозиторий себе на компьютер. Важно не скачать его как ZIP-архив, а именно склонировать.
Может быть полезно: Resources to learn Git
Перейдите в директорию с репозиторием. Для сборки и запуска ОС выполните одну команду:
$ make qemu
<...>
xv6 kernel is booting
virtio disk init 0
hart 1 starting
hart 2 starting
init: starting sh
$
Вы попали в шелл xv6. Попробуйте выполнить какие-нибудь команды:
$ ls
. 1 1 1024
.. 1 1 1024
xv6-readme 2 2 1982
xargstest.sh 2 3 93
<...>
$ cat xv6-readme
xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix
Version 6 (v6). xv6 loosely follows the structure and style of v6,
but is implemented for a modern RISC-V multiprocessor using ANSI C.
<...>
Чтобы выйти из QEMU, нажмите Ctrl-A
, затем X
.
Обратите внимание, что при перезапуске лишнего вывода перед запуском намного меньше. Это связано с тем, что перекомпилируются только измененные файлы.
Вы можете выполнить
make clean
, чтобы удалить все артефакты сборки и собрать ОС с нуля.
Прежде чем перейти к основной части курса, познакомимся подробнее с xv6 и её системными вызовами. Мы попробуем написать немного user-space кода.
Для решения этого задания создайте ветку user
в вашем репозитории и выполните задание в ней.
В вашем репозитории должно быть две ветки. Ветка
master
изменяться не должна. В веткеuser
должны быть только коммиты с вашим решением поверх того, что уже было вmaster
при выдаче задания. В репозитории должен быть только один PR с вашим решением. Изменять какие-то файлы, кромеMakefile
,user/pingpong.c
,user/sh.c
, нельзя.Похожие требования к оформлению предъявляются и для последующих домашних заданий — названия веток и файлов будут указаны в условии.
По возможности, разбивайте PR на отдельные коммиты, соответствующие частям вашего задания, и давайте коммитам читаемые имена.
Научитесь обмениваться данными между процессами с помощью специальных FIFO-каналов — Unix pipes. Реализуйте программу user/pingpong.c
, которая должна:
- Создать пайп.
- Создать дочерний процесс.
- Отправить сообщение из родительского процесса в дочерний.
- Прочитать их в дочернем процессе, вывести
<child pid>: got <message>
и отправить данные в ответ. - Прочитать ответ в родительском процессе, вывести
<parent pid>: got <message>
.
Советы для выполнения задания:
- Вам понадобится несколько системных вызовов —
pipe
,fork
,read
,write
,getpid
. Воспользуйтесь утилитойman
, чтобы узнать, что делают эти вызовы и как ими пользоваться — поведение в xv6 не особо отличается от других Unix-подобных операционных систем. - Вместо привычных вам
stdlib.h
иstdio.h
доступна местная стандартная библиотека — user/ulib.c, а также printf.c и umalloc.c. Посмотрите на другие программы в директории user/, чтобы понять, как ей пользоваться. - Добавьте программу в
UPROGS
вMakefile
, чтобы она скомпилировалась. - В программах для xv6 обязательно нужно вызывать
exit()
для выхода.
Обратите внимание на user/sh.c. Командная оболочка — тоже программа в user-space.
Данная командная оболочка позволяет запускать программы в фоновом режиме, например:
$ usertests &
В таком случае, пока выполняются тесты, вы сможете исполнять другие команды.
Добавьте в оболочку команду wait
, которая не принимает аргументов и дожидается выполнения всех дочерних процессов.
- Команду необходимо реализовывать прямо внутри
sh.c
. Подумайте, почему невозможно сделать это отдельной программой? - Обратите внимание на то, как реализована команда
cd
, и сделайте так же. - В xv6 процесс остаётся в зомби-состоянии, пока родительский процесс не вызовет
wait
.
После запуска
usertests
вам скорее всего понадобится вернуть оригинальную файловую систему. Для этого просто удалите файлfs.img
.
Это задание выполнять необязательно. Если вы его сделаете, то получите 4 бонусных балла. Обратите внимание, что на бонусные баллы штраф после дедлайна не накладывается. Но помните, что подзадание со звёздочкой сдаётся только вместе с основным — досдать его потом не получится.
Сейчас командная оболочка довольно неудобная, и у нас есть шанс сделать её лучше. В этом подзадании мы научимся поддерживать автодополнение команды по нажатию Tab. А именно, при нажатии Tab, если в текущей директории существует один или несколько файлов, названия которых начинаются с уже введенной строки, печатать их названия, а потом снова приглашение с введенной частью строки.
Предположим, пользователь нажал s<Tab>
. Он должен увидеть что-то такое:
$ s
sh
stressfs
$ s
Вам нужно работать с функцией getcmd — замените gets
на посимвольное чтение. Затем отдельно обработайте нажатие Tab (\t
). Используйте user/ls.c в качестве примера того, как правильно обходить директорию.
Обратите внимание на то, как реализована обработка нажатий клавиш в ядре в kernel/console.c.
У вас возникнет проблема с удалением символов, нажатых до Tab. В рамках данного задания её исправлять не требуется.
Однако, если вы хотите разобраться с этим, попробуйте добавить в xv6 системный вызов
ioctl
, и поддержите переключение в raw-режим и обратно. В этом режиме все нажатия клавиш на клавиатуре должны напрямую попадать в буфер, переданный вread
, и не отображаться на экране — а их обработка должна осуществляться в user-space (в нашем случае, вsh.c
).
Это подзадание не тестируется автоматически, оно проверяется преподавателем вручную.