LecturesCMC/Linux2017/02_ForkExecEnv
я георгий курячий, давно читаю лекции про всякое юниксовое, работаю в базальт спо, поэтому заком с темой. есть сайт UNИX
В прошлом семе был разговор про дистрибутивы, но это не совсем хорошо получилось, потому что пришлось много говорить про архитектуры юниксовых систем, и хотя про это говорили полсеместра, инфы все равно мало для тех, кто линукс сам не трогал, а только слышал. Поэтому в этом семестре хочется нагнать вот это всё упущенное.
Мы не будем говорить про всю систему целиком, то сееместра не хватит, поэтому мы будем говорить про юникс-систему как конструктор.
Идавльный план выглядел бы как-то так: - досистемная загрузка: на самом деле вообще не про линукс. как так получается, что в компьютер попадает ОС и начинает там функционировать - (возможно: промежуточные вещи (загрузчик и вот это всё), на которые может не хватить времени, а может и хватить) - ядро + его программный интерфейс(системные вызовы) + хеллоуворлд, который этим интерфейсом пользуется. "Линукс" это ядро и есть, на базе ядра можно сделать что угодно. юникс-подобная система на его основе изготовлена просто потому что не-юниксподобных нормальных систем-конструкторов просто не было. Можно дёргать вот эти вот системные вызовы напрямую, безо всякой ОС. - + минимальный командный интерфейс. не просто "есть утилиты", а потычем ручками какой-нибудь шелл-скрипт. - многопроцессность. Она существует отдельно от командного интерфейса. Возможно (поскольку этут тему всем жуют на 2 курсе) здесь же будет многопользовательскость (и права доступа). - "информация о системе" - если у нас есть устройство, надо чтобы оно было отображено в системе и, возможно, чтобы кто-то (какой-то процесс или процессы) оповещался о его появлении/исчезновении. сюда входит /proc, /sys, udev и прочее такое. - старт и работа *операционной системы*. Если нам нужно кроме ядра и оболочки еще запустить кучу других процессов (демонов), реконфигурировать в процессе всякие устройства и т.д. Здесь же появляются всякие новые современные веяния типа systemd. - межпроцессное взаимодействие: как вся эта куча компонентов обменивается между собой информацией. Есть posix'овые вещи - сигналы, семафоры, общая память, ... , а есть обмен типизированными сообщениями (dbus) - разделение доступа: как раздавать права процессам, которые их обычно не имеют, типа монтирования флешек в десктопе, совместного доступа к аудиовыходу и такого - policykit(polkit), а также как хитрее ограничивать права, если стандартных средств не хватает - SELinux и AppArmor - изоляция. как совсем, полностью и начисто отделять друг от друга процессы, ограничивать, скажем, память для группы процессов. или делать так, чтобы процессы из одной группы никак не видели ничего относящегося к другой. или делать несколько программных окружений, каждое со своим инитом, и т.д., но общим ядром. Волшебное слово - cgroups - freedesktop.org, его стандарты, seats и такое.
Будут виртуалочки, в которых каждый может потыкать всё вышеперечисленное своими руками.
Но тут есть методическая проблема, потому что если начинать с начала списка, то много кто ничего не поймёт, потому что в примерах непонятно, зачем эти страшные буквы в чёрном экране и что за заклинания туда вводятся. Поэтому мы начнем с командного интерфейса, оттуда спустимся вниз и поднимемся вверх, наблюдая примеры на основе уже изученного.
Чтобы смочь изучать минимально загруженную систему, минуя ее загрузку, будем использовать эмулятор qemu, который за нас всё запихает в память, как оно там должно лежать во время работы. "ты же эмулятор, какая тебе разница". мы ему говорим, где взять ядро и минимальную файловую систему и чтоб он остановился перед определением устройств, потому что сейчас нижняя часть списка нам не нужна
запускаем его, наблюдаем процесс загрузки (про который потом) и попадаем в командную оболочку. В командную щито? Вспомним прошлый сем. есть ядро, есть утилиты, которые делают частоиспользуемые вещи (имзначально просто дергали системные вызовы), чтобы всё это не писать всё время на си. А рядом есть программа, которая называется шелл, или оболочка, которая и работает командным интерфейсом системы, запуская эти самые утилиты по команде пользователя.
Запустим команду (утилиту) ps и увидим кучу процессов, большинство из которых на самом деле кусочки ядра, а настоящих пользовательских процессов всего 2 - шелл и ps, через него запущенный.
Здесь надо отметить важную вещь: В любой момент в системе работает ровно один процесс, а все остальные ждут. Если посмотреть в правильную колонку вывода ps ax, то мы видим, что все процессы кроме ps спят (буковка S), а ps работает (буковка R).
Вспомним еще, как вообще запускаются процессы. вообще это было на 2 курсе, но еще раз вспомним. сначала вызывается fork(), получается 2 совершенно одинаковых процесса, единственная разница - в родителе форк возвращает pid потомка, а в потомке 0. дальше потомок вызывает exec(), который подменяет его другой программой. тем временем родитель (который все еще шелл) ждет завершения потомка (который теперь стал вызываемой программой). Поэтому мы и видим, что ps работает, а шелл ждёт. За дальнейшими подробностями этого всего - в курс осей и прака.
Когда мы запускали эмулятор, мы говорили эмулятору про ядро и про некий initrd, который есть минимальная файловая система, загружаемая целиком в оперативную память. Посмотрим на нее подробнее. В ней есть 15 директорий и один исполнятемый файл init (в системе на самом деле еще прячется третий процесс, мы немного соврали выше. этот инит, кстати, на самом деле является шелл-скриптом).
Эту ФС вам надо будет изучить в качестве ДЗ.
Вообще раз уж мы про это заговорили, поговорим еще. Если подняться в нашем списке на строчку выше (или логически на ступеньку ниже), то мы можем ыообще жить безо всякой ФС, а иметь просто ядро и одну-две программы, которые им пользуются, для этого не нужно никакой ФС и никаких каталогов. Кстати, и сами каталоги вещь хоть и давняя, но появившаяся намного позже появления компьютера.
Давайте, кстати, переделаем инитрд. это немного альтлинукс-специфичное, но какая разница. есть программа make-initrd, которая создает и запаковывает этот начальный минимальный образ корневой файловой системы. подредактируем конфигурационный файл (где единственная строка - "какие программы добавить к стандартному образу"), чтобы в образе была еще команда find (а также ed и more), запустим make-initrd с правильные=ми параметрами, которые вы можете посмотреть самостоятельно, и получим новый образ. Повторим загрузку эмулятора, увидим новый файл.
Запустим свежеобретенный find и увидим список всех файлов на стопицот экранов, большинство которых находятся в /sys, то есть виртуальные и не существуют на самом деле как блоки с информацией. Можно посмотреть man hier и почитать, что где лежит в стандартной системе каталогов. там те же каталоги, что и в нашей минимальной ФС. Только в этом мане еще рассказывают много всяких вещей про то, как вообще построена система.
Уже имея лишь ядро, минимальную ЫС и шелл, можно делать всякие интересные конструкции, исходя из шелла как языка программированиЯ. Об этом мы поговорим потом, но возможноть это делоть появляется чуть ли не сразу.
про сущность файловых систем. у понятия "файловая система" есть два смысла: во-первых, способ размещения файлов на физическом блочном устройстве (диске) , а во-вторых, логическая структура организации имён файлов (структура каталогов). Вот структура каталогов в юникс-системе всегда одна и вышлядит как дерево с одним корнем. Файловые системы в первом смысле можно встраивать в это дерево каталогов, подвешивая их как поддерево. Операция называется монтированием и делается при помощи команды mount.
Продолжаем изучение минимальной ФС.
про /lib. Там живут библиотеки, которые нужны для работы нашим программам. Недостаточно скопировать в нашу собираемую систему только бинарник, надо еще добавить библиотеки, которыми он пользуются, а также библиотеки, которыми пользуются эти библиотеки, итд до замыкания множества.
В /etc живут всякие конфигурационные файлы. В initrd их мало, а в большой полноценной системе тысячи.
Из наших игр с минимальной системой начинает быть видно, чего еще нам не хватает. Нужно больше команд (потому что у нас командный интерфейс), нужно передавать сигналы работающим процессам (потому что сейчас шелл просто ждёт завершения команды, а ты беспомощно на это смотришь) и так далее. С другой стороны, если ты конструируешь РЕШЕНИЕ, специализированный инструмент, за которым не будет работать человек, то этого может быть даже много, и что-то можно убрать.
Итак, это было введение и краткий обзор того, что будет. В следующий раз мы еще поговорим о командном интерфейсе, потому что на нем основаны все наши примеры, оставайтесь с нами. Вскоре будет виртуалка для этого, а еще qemu работает в винде.
Спасибо за внимание, приходите к нам еще.