*https://www.youtube.com/watch?v=eBqMWeVVzXE
**https://300.ya.ru/summary
таймкоды
00:00:00 Введение в Linux
- Linux — это ядро, управляющее железом, а не операционная система.
- При включении сервера процессор ищет первую инструкцию по жёстко заданному адресу.
- Прошивка материнской платы BIOS или UEFI запускает POST и опрашивает устройства.
00:00:51 Загрузка системы
- BIOS считывает MBR или раздел EFI с загрузчиком Grub 2.
- Grub распаковывает ядро Linux VM-Linux в оперативную память.
- Ядро сталкивается с проблемой «курицы и яйца»: для монтирования диска нужны драйверы, которых ещё нет.
00:01:50 Initramfs и Pivot Root
- Grub загружает initramfs — временный архив с драйверами.
- Ядро монтирует initramfs как временный корень и загружает драйверы для оборудования.
- После загрузки драйверов ядро выполняет Pivot Root, заменяя временный диск на настоящий.
00:03:44 Монолитное ядро
- Все драйверы и сервисы работают в едином адресном пространстве, обеспечивая высокую производительность.
- Монолитное ядро повышает риски, например, при выходе из строя драйвера видеокарты может вызвать kernel panic.
00:04:28 Управление памятью
- Ядро использует виртуальную память для изоляции процессов и свопинга.
- OOM-killer убивает процессы, потребляющие много ресурсов, если память заканчивается.
00:05:27 Планировщик процессов
- Планировщик распределяет время между процессами, используя вытесняющую многозадачность.
- Переключение контекста происходит тысячи раз в секунду.
00:06:25 Абстрагирование оборудования
- Ядро предоставляет универсальный интерфейс для пользовательских программ, позволяя им работать на любом оборудовании.
- Программы обращаются к ядру через системные вызовы.
00:07:23 Системные вызовы
- Системные вызовы — это API, через который программы взаимодействуют с ядром.
- Основные системные вызовы: fork, exec, open, close, read, write, socket, connect.
- S-Trace помогает отлаживать программы, показывая, что они пытаются сказать ядру.
00:09:11 Запуск системы
- Ядро запускает процесс init с PID 1.
- init управляет загрузкой других процессов, таких как SSH и Docker.
- Система управляет нагрузками и запускает необходимые демоны.
00:11:57 Виртуальная файловая система
- VFS — это универсальный интерфейс для работы с различными типами хранилищ: SSD, сетевые диски, оперативная память.
- Программы видят только дерево каталогов, а VFS решает, куда отправить байты.
00:12:53 Прозрачность абстракции и структура файла
- Файл для пользователя — это название, например, photo.jpg, но для ядра это набор байтов.
- Ядро обрабатывает файл как inode — индексный узел, содержащий метаинформацию и указатели на сектора диска.
- Имя файла хранится в каталоге, который представляет собой таблицу с именем файла и номером inode.
00:13:42 Концепция «всё есть файл»
- В Linux ядро представлено как набор файлов, доступных через папки proc и sys.
- Чтение файлов proc/cpuinfo не требует обращения к диску, ядро генерирует ответ на лету.
- Запись в файлы proc позволяет управлять системой, например, включать маршрутизацию пакетов.
00:14:39 Процессы и каналы связи
- Процесс — это изолированный контейнер в памяти с PID, переменными и ресурсами.
- Ядро открывает три файла для процесса: stdin стандартный ввод, stdout стандартный вывод и stderr стандартный вывод ошибок.
- Разделение stdout и stderr позволяет отделять полезные данные от ошибок.
00:16:35 Межпроцессное взаимодействие через pipes
- Pipes позволяют создавать конвейеры из процессов, которые не знают о существовании друг друга.
- Пример: cat | grep создаёт конвейер, где cat пишет в буфер, а grep читает из того же буфера.
- Подход Unix основан на взаимодействии программ через текстовые потоки.
00:17:34 Безопасность в Linux
- Безопасность обеспечивается проверкой битов в inode, где хранятся права доступа.
- UID и GID преобразуются в битовые маски для управления правами.
- Право execute для каталога означает возможность доступа, а не запуск файла.
00:19:27 Роль root и sudo
- Root имеет UID 0 и может выполнять системные вызовы без проверки прав.
- Sudo временно повышает UID до 0, выполняя команду и записывая её в журнал аудита.
- Это обеспечивает безопасность без потери контроля.
00:20:24 Установка программ в Linux
- Программы устанавливаются через централизованные репозитории и пакетные менеджеры, такие как APT, Yama, PK.
- Пакетный менеджер проверяет наличие необходимых библиотек и устанавливает программы в соответствии со стандартом FHS.
- Динамическая связь программ экономит ресурсы, но требует соответствия версий библиотек.
00:22:22 Инженерное мышление в Linux
- Понимание архитектуры Linux помогает решать проблемы и избегать «dependency hell».
- Инженерное мышление позволяет анализировать ошибки и оптимизировать систему.
- Знание архитектуры Linux делает пользователя более эффективным.
00:24:07 Заключение
- Призыв стать инженером и понять основы архитектуры Linux.
- Рекомендация скачать карту архитектуры Linux для лучшего понимания.
Transcript
0:00
Всем привет. Вы на канале Просто
0:01
Devоops. Мы часто говорим слово Linux,
0:04
подразумевая операционную систему
0:05
Убунту, Центоз, Debн, но с инженерной
0:08
точки зрения это неверно. Linux — это
0:11
ядро. По сути кусок кода, который
0:13
управляет железом. А всё, что мы видим
0:16
на экране, всё, с чем мы взаимодействуем
0:18
это просто набор программ, которые
0:20
крутятся поверх этого ядра. И в этом
0:22
видео мы разберёмся, как этот самый
0:24
Linux устроен. Начнём с самого низа, а
0:28
именно с железа. Нажимаем кнопку питания
0:30
на сервере. Пошёл ток. Процессор
0:32
просыпается, но в этот момент он пока
0:35
что тупой кусок кремния. Он не знает,
0:37
что такое Linux. Он не знает, что такое
0:39
файлы. Он даже не знает, сколько у него
0:41
оперативной памяти. Он просто ищет
0:43
первую инструкцию по жёстко заданному
0:45
адресу. Первый стартует прошивка
0:46
материнской платы BIOS или же Wi-Fi. Её
0:49
задача — привести железо в чувство. Она
0:52
запускает пост power on self-теest,
0:55
проверяет, есть ли память, работает ли
0:57
видеокарта, инициализировался ли
0:59
процессор, нашёл ли он оперативку и так
1:02
далее. Затем она начинает опрашивать
1:04
устройство и ищет, с кого можно
1:06
загрузиться.
1:09
Допустим, она нашла жёсткий диск, но
1:11
BIOS сам не умеет читать файловые
1:14
системы. Он не знает, что такое XT4 или
1:16
XFS. Он не может просто взять и открыть
1:19
файл, поэтому он считывает самые первые
1:22
512 байт диска. Это MBR или же смотрит в
1:26
специальный Ефии раздел. А там живёт
1:28
загрузчик. В мире Linux — это почти
1:30
всегда Граб 2. Граб — это маленькая, но
1:33
умная программа. Её единственная
1:35
способность, она умеет читать файловую
1:38
систему. Заглядывает в раздел boot. Там
1:41
лежат два критически важных файла, без
1:43
которых никакой магии не случится.
1:45
Первый файл — это VM Linux. По сути, и
1:48
есть тот самый Linux. Это само ядро,
1:51
сжатое в бинарный файл. Буква Z в конце
1:54
означает zip, то есть сжатый. Граб берёт
1:57
этот файл, распаковывает его прямо в
1:59
оперативную память и передаёт ему
2:01
управление. Всё. С этого момента BI
2:04
уходит курить в сторонку, загрузчик
2:06
умирает. Теперь в системе только один
2:08
босс — это ядро. И [музыка] вот тут ядро
2:11
сталкивается с главной инженерной
2:13
проблемой, проблемой курицы и яйца. Ядро
2:15
загрузилось в память. Его задача
2:17
смонтировать наш основной диск, чтобы
2:19
запустить систему. Но чтобы смонтировать
2:22
диск, нужны драйверы файловой системы и
2:24
контроллера диска. А где лежат драйверы?
2:27
Правильно, на том самом диске, который
2:29
мы ещё не можем прочитать, потому что у
2:31
нас нет драйверов. Замкнутый круг.
2:33
Именно для этого Граб загрузил второй
2:35
файл InitramfS. Это маленький временный
2:38
архив, который разворачивается в
2:40
оперативной памяти как виртуальный диск.
2:42
Внутри него лежит мини-версия Линукса с
2:45
минимальным набором драйверов.
2:47
Соответственно, что происходит? Ядро
2:49
монтирует Иit Ram FS как временный
2:51
корень. Оттуда оно подгружает драйверы
2:53
для нашего реального железа.
2:55
Рейд-контроллеры, NVME, LVM и так далее.
2:58
Далее оно находит настоящий большой диск
3:02
и делает трюк под названием Pvot root,
3:04
то есть смена корня. Ядро выкидывает
3:06
временный диск из памяти и заменяет его
3:09
настоящим. Если сервер виснет на этапе
3:11
загрузки с ошибкой, которую вы видите на
3:14
экране, это значит, что ядро застряло
3:17
именно в этом моменте. Оно либо не нашло
3:19
ИitромFS, либо внутри него не оказалось
3:22
нужного драйвера для диска. Итак,
3:25
загрузчик отработал, драйверы
3:26
подгрузились, мы попадаем в knalel
3:29
Space. С точки зрения архитектуры
3:31
процессора мы находимся в кольце защиты
3:34
RН. Здесь разрешено всё: любая
3:37
инструкция процессора или любой адрес
3:40
памяти. Linux — это монолитное ядро, а
3:42
не набор разрожденных сервисов. Драйвер
3:44
видеокарты, сетевой стек TCPIP, драйвер
3:47
файловой системы XT4. Всё это варится в
3:51
одном гигантском котле в едином адресном
3:53
пространстве. И это даёт дикую
3:55
производительность, потому что нет
3:57
накладных расходов на общение между
3:59
компонентами. Но это повышает риски.
4:01
Если драйвер кривой видеокарты упадёт,
4:04
он утащит за собой весь сервер в KNAL
4:07
Pic. [музыка] А у самого ядра есть три
4:09
основных задачи. Сейчас посмотрим на
4:11
каждую из них. Первое — это управление
4:13
памяти. И на самом деле здесь главная
4:16
задача ядра — врать. Оно врёт нашим
4:19
программам. Когда условный Инжинс или
4:21
Python просит память, он думает, что
4:23
единственный в системе. Для него
4:25
[музыка] всё выглядит как красивая
4:26
непрерывная лента адресов. Хотя на самом
4:29
деле физическая память фрагментирована,
4:32
и куски данных разбросаны хаотично. Ядро
4:34
использует механизм виртуальной памяти.
4:37
Оно ведёт гигантскую таблицу, где
4:39
записано: «Виртуальный адрес X для
4:41
процесса Ins на самом деле лежит в
4:43
физической ячейке Y. И это даёт две
4:46
вещи. Первое — изоляция. Один процесс
4:49
физически не может залезть в память
4:51
другого. А второе — это свопинг. То есть
4:54
ядро может незаметно выгрузить часть
4:56
данных на диск, если оперативка
4:58
закончилась. Но если память кончилась
5:00
совсем и своп тоже забит, то приходит
5:03
омкиллер. И он неспроста так назван. Это
5:05
буквально киллер, который нанял ядро. Он
5:08
просыпается, сканирует таблицу процессов
5:11
и находит того, кто ест больше всех и
5:14
имеет при этом низкий приоритет, и
5:16
пускает ему пулю в лоб. Например, в том
5:18
же Кубере это происходит постоянно. Если
5:21
мы неправильно настроим лимиты в кодах,
5:23
то омкилillлер будет приходить и молча
5:25
убивать наше приложение. Вторая задача
5:28
ядрать время между процессами. И для
5:31
этого существует так называемый
5:33
планировщик процессор. Допустим, у нас
5:35
на сервере четыре ядра, а запущено 500
5:38
процессов. Как они работают
5:39
одновременно? [музыка] Никак. Это
5:41
иллюзия. Ядро использует вытесняющую
5:44
многозадачность. Оно даёт процессу
5:47
проработать несколько миллисекунд, так
5:49
называемый квант времени. а потом жёстко
5:51
его останавливает, и происходит свитч
5:54
контекста. То есть ядро сохраняет
5:56
состояние регистров процессора [музыка]
5:57
для текущей задачи, загружает состояние
6:00
для следующей задачи и нажимает Play. И
6:03
это происходит тысячи раз в секунду.
6:06
Если мы видим в мониторинге высокий LТ
6:08
average, но процессор не загружен на
6:10
100%, возможно, система тратит всё время
6:13
не на работу, а на бесконечное
6:15
переключение контекста между тысячами
6:17
процессов. А про Load average у нас,
6:19
кстати, было видео. Вот оно. Ну и третья
6:22
задача ядра — это абстракция
6:24
оборудования. Если говорить по простому,
6:27
то ядро выступает в качестве
6:28
переводчика. Программы, которые запущены
6:31
в юзерспейсе, то есть наши программы
6:33
пользовательские, не знают железа. Вот
6:36
условно у нас есть программа на Питоне,
6:38
которая записывает одно слово в файл, но
6:40
только Python не знает, куда он
6:42
записывает. На самсунговскую сиздишку,
6:44
на какой-то старый жёсткий диск или
6:46
вообще на сетевую шару. У каждого диска
6:48
свой протокол, свои вольтажи, свои
6:51
команды контроллера, а ядро
6:52
предоставляет универсальный интерфейс.
6:55
Программа буквально говорит: «Пиши в
6:57
этот файл». А драйвер ядра переводит это
6:59
в электрические сигналы. И благодаря
7:01
этому наш код работает одинаково на
7:04
любом железе. Двигаемся выше. У нас есть
7:07
ядро, которое всем управляет. И есть
7:09
наши программы, которые хотят что-то
7:12
сделать: прочитать файл, отправить пакет
7:14
или вывести текст на экран. Но есть
7:16
проблема. Между режимом пользователя,
7:18
где живут наши программы, и режимом
7:20
ядра. Стоит бетонная [музыка] стена.
7:23
Процессор физически запрещает коду из
7:25
юзерспейса обращаться к оборудованию. И
7:28
если наша программа пытается напрямую
7:31
обратиться к диску, процессор немедленно
7:33
её убьёт с ошибкой Segmentation Fold. И
7:35
как же нам быть? На самом деле, в этой
7:38
стене есть однаединственная
7:39
бронированная дверь. Она называется
7:42
системный вызов. Это строго
7:44
регламентированный АПИ. Ядро говорит,
7:46
что оно не пустит нас к диску, но если
7:49
мы вежливо попросим через специальную
7:51
функцию, то оно сделает это за нас. И
7:54
давайте рассмотрим это на примере того
7:55
же Питона. Вот мы пишем Print Hello
7:58
World, но происходит целая цепочка
8:00
событий. Интерпретатор питона вызывает
8:02
стандартную библиотеку C gpc. Библиотека
8:05
формирует системный вызов Rightй. Она
8:07
кладёт аргументы в регистры процессора и
8:10
генерирует специальное программное
8:12
прерывание. Процессор останавливает
8:15
программу, переключает режим в ринг
8:17
ноль, тот самый режим бога, о котором мы
8:19
говорили в самом начале, и передаёт
8:22
управление ядру. Ядро проверяет, а есть
8:24
ли у этого юзера права писать в этот
8:27
файл. И если всё о’кей, то ядро рисует
8:30
пиксели на экране или пишет байты на
8:32
диск, а дальше возвращает управление
8:34
программе. И на самом деле системных
8:36
вызовов великое множество, их в районе
8:38
300-400. Но основные сисколы, которые
8:41
нужно знать, на которых держится вся
8:44
база, сейчас у вас на экране. Это Fork
8:47
Exeg, это Open и Close, это Rit и Right,
8:50
это Socket и Connect. Но зачем это знать
8:52
именно Divпсу? А потому что программы
8:54
часто врут. Логи могут быть пустыми, а
8:57
ошибки неинформативными. Но программа не
9:00
может врать [музыка] ядру. Она обязана
9:02
давать все ссколы, чтобы хоть что-то
9:04
сделать. И здесь на сцену выходит самый
9:07
главный инструмент отладки Sraйс. Это
9:10
прослушка для сисколов. Мы запускаем
9:12
Sraйс на какой-то процесс и видим всю
9:15
подноготную, что он пытался сделать,
9:17
[музыка] что он получил или на чём он
9:19
завис. Sraйс — это рентген. Он
9:22
показывает нам, что программа пытается
9:24
сказать ядру на самом деле. И если вы
9:26
умеете читать выводст, то для вас не
9:29
существует непонятных багов. Продолжаем
9:32
двигаться вверх по стеку. Ядро
9:34
загрузилось, инициализировало память и
9:36
драйверы, но сервер всё ещё пустой. В
9:38
нём нет ни СШ, ни консоли, ни сети.
9:41
Чтобы система ожила, ядро должно
9:43
запустить самый первый процесс в
9:45
пространстве пользователя. И для этого
9:47
оно ищет на диске исполняемый файл по
9:50
адресу sbin/it и запускает его. Этот
9:53
процесс получает ПиIT 1, его уникальный
9:57
айдишник. Все остальные процессы в
9:59
системе Пит 2, 3, 4.000, 10.000
10:02
будут потомками этого процесса. Если
10:05
первый процесс умрёт или завершится, яро
10:08
решит, что система сломалась и вывалится
10:10
в KNAL Pic и сервер встанет. А в
10:13
современном Линуксе роль первого
10:15
процесса выполняет System D. А почему
10:17
именно System D? Раньше, во времена
10:19
CSway и процессы запускались тупо по
10:22
очереди. Сначала сеть, потом диск, потом
10:25
база. Это было долго. System D работает
10:28
как менеджер зависимостей. Он строит
10:31
направленный граф, кстати, как в
10:33
тероформе. Условно говоря, он видит так:
10:36
зависит от сети, пагress зависит от
10:38
диска, а SSH ни от чего не зависит и
10:41
запускает всё это параллельно,
10:43
максимально утилизируя процессор при
10:45
загрузке. А что физически делает Systemd
10:48
при старте? Во-первых, он монтирует
10:50
реальные диски в дерево каталогов.
10:53
Во-вторых, он определяет цель загрузки
10:55
и, в-третьих, [музыка] начинает
10:57
поднимать юниты. запускает SSHD, чтобы
11:00
мы могли подключиться, запускает демон
11:02
докера, чтобы поднялись контейнеры, и
11:05
так далее. При этом мы, как админ, не
11:07
можем просто сказать процессу:
11:09
«Запустись». Мы общаемся с пиtit
11:12
System CTL. Когда мы пишем System CTL
11:15
start Engines, по сути, мы отправляем
11:17
команду System D через определённый
11:20
сокет. System D, есть ли у нас права,
11:23
смотрит в зависимости инжинкса и
11:25
выполняет системный вызов Fork, то есть
11:28
создаёт копию себя, и exeg, то есть
11:31
заменяет копию на бинарник Инжнкса. Так
11:34
рождается процесс веб-сервера. Он
11:36
ребёнок систем D.
11:40
Итак, процессы запущены, но процессы в
11:43
вакууме бесполезны. Им нужно читать
11:45
конфиги, писать логи, сохранять
11:47
картинки. Мы поднимаемся ещё на
11:49
следующий уровень абстракции файловой
11:51
системы. И здесь царит главная философия
11:54
Unix. Всё есть файл. Но давайте разберём
11:58
это не как лозунг, а как инженерное
12:00
решение. В винде все привыкли к буквам
12:02
дисков C, D, E, F и так далее. Это
12:06
физическое разделение устройств. В
12:08
Линуксе подход другой. [музыка] Здесь
12:10
существует единое дерево каталогов. Оно
12:13
всегда начинается с корня, то есть
12:15
символа слыша. Процессу плевать, сколько
12:17
у нас дисков. Он видит только дерево. Ну
12:20
и, соответственно, как это работает
12:22
физически. Внутри ядра есть прослойка
12:25
VFS. Виртуальная файловая система. Это
12:28
точно также универсальный интерфейс. Мы
12:30
берём условный SSD-диск и говорим ядру.
12:33
Примонтирую его в папку boot. Потом
12:35
берём сетевой диск и говорим
12:37
примонтировать его в другой каталог.
12:39
Берём оперативную память и монтируем её
12:42
в RН. Для программы всё это выглядит
12:45
одинаково. [музыка] Она просто пишет
12:47
файлы по путям, а ВФэска сама на лету
12:50
решает, куда отправить эти байты. По
12:53
кабелю SAD или по сетевому кабелю на
12:56
другой сервер. Это и есть прозрачность
12:58
абстракции. Теперь спускаемся ниже. Что
13:01
такое файл физически? Для нас [музыка]
13:04
это просто какое-то название, условно
13:06
photo. JPG, но для ядра имя — это пустой
13:09
звук. Просто набор байт для удобства
13:11
кожаного мешка. Для ядра файл — это
13:14
iнода, индекс нода. Каждый файл в
13:17
системе — это просто номер. В айноде
13:19
хранится вся метаинформация, кроме
13:21
имени: кто владелец, какие права
13:23
доступа, размер файла, тайм-стампы и
13:26
самое главное, указатели на сектора
13:28
диска, где физически лежат нулее
13:31
единицы. А что тогда такое имя файла?
13:34
Имя живёт в каталоге. И технически
13:36
каталог, то есть папка — это тоже файл,
13:39
но внутри него лежит простая таблица из
13:41
двух колонок: имя файла и номерноды. И
13:44
когда мы, например, выполняем команду C
13:46
и передаём ей имя файла, то ядро в этот
13:48
момент читает каталог, находит имя,
13:52
берёт соответствующий номер иноды, потом
13:54
идёт в таблицу ит, смотрит права и
13:57
сектора диска и после этого начинает
14:00
читать данные. Ну, а теперь давайте
14:02
раскроем концепцию всё есть файл на
14:04
полную. Помните, мы говорили, что VFS —
14:07
это абстракция? Так, разработчики
14:09
Линукса подумали: «А зачем нам
14:10
ограничиваться дисками? Давайте
14:12
представим само ядро в виде файлов».
14:15
Итак, появились папки проs и SIS. В них
14:18
нет файлов на диске. Размер этих файлов
14:20
0 байт. Это иллюзия, но это прямой
14:24
интерфейс доступа к структурам данных
14:26
ядра в оперативной памяти. И, например,
14:28
когда мы читаем файл процpu
14:31
ядро не идёт на диск, оно опрашивает
14:33
процессор и генерирует текст ответа на
14:36
литу. И самое крутое — это работает в
14:39
обе стороны. Мы можем писать в эти
14:41
файлы. Хотим включить маршрутизацию
14:43
пакетов, то есть стать роутером. Нам не
14:45
надо искать никакую галочку ни в какой
14:47
панели управления. Мы просто пишем цифру
14:49
один вот в этот файл, который показан на
14:52
экране. Ядро перехватывает эту запись и
14:55
меняет переменную в своём коде. Вот что
14:57
значит всё есть файл. Это универсальный
15:00
апи для управления системой. Мы
15:02
разобрались с хранением, то есть с
15:04
нашими файловыми системами. Теперь
15:06
переходим к исполнению. Что такое
15:09
запущенная программа? Это процесс.
15:12
Процесс — это изолированный контейнер в
15:15
памяти, у которого есть свой PID, свои
15:18
переменные и свои ресурсы. Но процесс в
15:21
вакууме бесполезен. Ему нужно получать
15:24
данные и отдавать результат. И здесь
15:26
снова работает правило, всё есть файл.
15:28
Когда ядро запускает любой процесс, оно
15:31
автоматически открывает для него три
15:33
файла, то есть три канала связи. В
15:35
таблице файловых дескрипторов они всегда
15:37
занимают первые три строчки. Первый из
15:39
них, хотя, вернее сказать, нулевой — это
15:42
DDIN, то есть стандартный ввод. По
15:44
умолчанию этот файл привязан к нашей
15:46
клавиатуре. Процесс читает оттуда то,
15:48
что мы печатаем. Второй — это D out, то
15:51
есть стандартный вывод. По умолчанию
15:53
этот файл привязан к нашему экрану, ну
15:56
или же терминалу. Сюда летит результат.
15:58
Иdr, стандартный вывод ошибок тоже
16:01
привязан к экрану, но это отдельный
16:03
поток. А зачем разделили stdout и stdr?
16:06
На самом деле, чтобы мы могли отличить
16:08
мух от котлет. Если программа работает и
16:11
сыпет ошибками, мы можем сказать
16:13
оболочки. Полезные данные, то есть
16:15
первый индекс, записать в файл data.txt,
16:18
а ошибки, то есть второй индекс, просто
16:20
выкинуть в defnal чёрную дыру. В девопсе
16:23
это база логирования. А теперь переходим
16:25
к главной магии Linux, символу
16:27
вертикальной черты Pйpe. Это механизм
16:31
межпроцессного взаимодействия. Возьмём
16:33
вот эту команду. Как она работает? Ядро
16:36
запускает процесс C и процесс греп
16:38
одновременно, но для CAT оно подменяет
16:41
stdout, то есть выход, и вместо экрана
16:44
оно направляет его в специальный буфер
16:46
памяти пайп. А для ГЕБ ядро подменяет
16:49
его, то есть вход. И вместо клавиатуры
16:52
он подключает его к тому же самому
16:54
буферу. И в чём гениальность? Процессы
16:57
КТ и ГП не знают о существовании друг
16:59
друга. Кэт думает, что пишет на экран, а
17:02
Греб думает, что читает с клавиатуру.
17:04
Ядро просто переткнуло провода, и это
17:07
позволяет строить конвейеры любой длины.
17:09
Вот посмотрите на экран. Пять глупых
17:12
маленьких программ, соединённых пайпами,
17:14
превращаются в мощный инструмент
17:16
аналитики. Это и есть подход Юникса.
17:18
писать программы, которые делают одну
17:21
вещь, но хорошо, и научить их работать
17:24
вместе через текстовые потоки. Мы
17:26
разобрались, как процессы работают и как
17:29
данные летают по пайпам. Но кто решает,
17:31
кому можно читать файл, а кому нельзя?
17:34
Мы поднимаемся [музыка]
17:35
на уровень безопасности. В Линуксе
17:37
безопасность — это не магия антивируса,
17:39
это простая проверка битов в Вайноде.
17:42
Когда мы логинимся в систему, мы думаем,
17:44
что пользуемся админкой. Но ядро не
17:46
знает слов. Ядро знает только цифры.
17:48
Наше имя транслируется в UID, user ID.
17:52
Наша группа транслируется в Git, Group
17:55
ID. Это база данных соответствии лежит в
17:57
простых текстовых файлах PVD и etcoup. И
18:01
помните, мы говорили пройноды. В каждой
18:03
аноде записано: «Этим файлом владеет UID
18:06
такой-то, группа [музыка] такая-то. И
18:08
там же записаны три набора прав: usеer,
18:11
то есть, что может делать владелец,
18:13
group, то есть, что может делать группа,
18:16
иers, что может делать любой другой
18:18
рандомный процесс. А сами действия
18:20
примитивны: read, [музыка] то есть
18:22
читать, write, то есть изменять, и
18:24
execute, то есть сказать ядру, загрузить
18:26
[музыка] этот файл в память и исполнить
18:28
как процесс. И каждое действие имеет
18:30
своё число. read 4, write 2, execute 1.
18:34
Почему именно это? Это не случайные
18:37
цифры. Это битовая маска в двоичной
18:39
системы. Чтение — это 100, запись — это
18:43
0,10, исполнение — это 01. И когда мы
18:46
пишем условно чмот 755, мы просто
18:48
складываем биты. 7 — это 4 + 2 + 1.
18:52
Владелец [музыка] может всё. 5 — это 4 +
18:55
0 + 1. То есть группа может читать и
18:57
исполнять, но [музыка] не писать. Ну и
19:00
ещё раз пятёрка для всех остальных. И
19:02
здесь есть важный нюанс. Право [музыка]
19:04
X, то есть execute для каталога означает
19:07
не запуск, а возможность в него попасть.
19:09
Если у нас есть права на чтение папки,
19:11
но нет права на вход, то мы можем
19:13
увидеть список файлов, но не можем
19:15
прочитать их метаданные. Но у всех
19:17
правил есть исключение. [музыка] В
19:19
Линуксе есть один пользователь, для
19:21
которого ядро отключает проверку прав.
19:24
Это [музыка] root. У него всегда UID0.
19:27
Когда процесс UID0 делает CS call open,
19:30
ядро не смотрит в айноду, оно просто
19:32
открывает файл. Root может читать etcad,
19:36
где лежат хэши паролей, может убить
19:38
процессы и ниты, положить сервер, может
19:40
отформатировать диск на живой системе,
19:42
поэтому сидеть под рутом — это дурной
19:44
тон и риск. Для администрирования
19:47
используется [музыка] механизм суда. Это
19:49
утилита с особым битом SUID, которая
19:52
временно повышает наш UID до нуля,
19:55
выполняет одну команду и, что критически
19:57
важно, записывает это в лок аудита. Так
20:00
мы получаем безопасность без потери
20:02
контроля. И вот мы поднялись на самый
20:04
верхний уровень userspace. У нас есть
20:07
[музыка] ядро, есть файловая система,
20:09
есть права, но система всё ещё голая.
20:12
Нужен софт, веб-серверы, база данных,
20:14
утилиты. Как программы попадают в Linux?
20:16
В Виндоусе все привыкли делать, как идём
20:18
на сайт, качаем экзэшник, кликаем Next,
20:21
и каждая программа тащит с собой свои
20:23
собственные библиотеки. В Линуксе принят
20:25
инженерный подход. Централизованные
20:28
репозитории. Это проверенные склады
20:30
бинарных пакетов, которые поддерживаются
20:33
разработчиками вашего дистрибутива.
20:35
Здесь работает пакетный менеджер АТ,
20:37
Яма, ПК. Когда мы пишем APT installings,
20:41
происходит не просто скачивание.
20:42
Пакетный менеджер — это умный архиватор
20:45
с базой данных. Он скачивает топ или то
20:48
rpm пакет, распаковывает файлы строго по
20:50
стандарту FHS, то есть бинарник [музыка]
20:53
кладёт в userbin, configги в etc,
20:55
сервисный файл в lipstem [музыка] D
20:58
system. Ну а самое важное, он проверяет,
21:01
есть ли у нас нужны библиотеки. Почему
21:03
это важно? Потому что Linux экономит
21:05
ресурсы. Программы в Линуксе почти
21:07
всегда динамически слинкованы. Это
21:10
значит, что бинарник Джинкса весит
21:12
копейки. В нём нет кода шифрования, в
21:14
нём нет кода сжатия. Вместо этого он
21:17
просто [музыка] при запуске говорит
21:19
ядру: «Мне нужна такая-то библиотека». И
21:21
ещё вот такая. А сами эти библиотеки
21:24
шареные. Они лежат в системе в одном
21:26
экземпляре, обычно в Userер и когда мы
21:29
запускаем условный Engin SSH клиент и
21:32
Python Script, все они используют один и
21:34
тот же файл библиотеки. Ядро загружает
21:37
её в оперативную память один раз, и все
21:40
процессы просто получают ссылку на этот
21:42
участок памяти. И это колоссально
21:44
экономит оперативку, но при этом создаёт
21:47
сложность. Версии библиотек должны
21:49
совпадать. Именно поэтому нам нужен
21:51
пакетный менеджер, а не ручное
21:53
скачивание файлов. Он следит, чтобы
21:55
версия библиотеки в системе подходила
21:57
всем установленным программам. А если
21:59
этот карточный домик рушится, это
22:01
называется Dependency Hell, то есть ад
22:04
зависимостей. [музыка]
22:05
Но в современных дистрибутивах это
22:07
случается крайне редко. Ну и теперь
22:10
давайте соберём этот пазл воедино. Мы
22:12
прошли путь от холодного кремния до
22:15
нашей клавиатуры. Теперь у вас в голове
22:17
должна быть не каша из команд, а чёткая
22:19
вертикальная структура. Смотрите на
22:21
Linux как инженер. Внизу лежит тупое
22:23
железо, которое разбудил BIOS. Над ним
22:26
стоит диктатор. Ядро. Оно врёт
22:28
программам про память, нарезает время
22:30
процессора и управляет драйверами. Между
22:33
ядром и миром бетонная стена с одним
22:35
окошком. Никто не проходит мимо. Ядро
22:38
запускает первого рабочего, который
22:40
строит всё окружение юзерспейса. И всё
22:43
это пространство организовано в единое
22:45
дерево, где каждый файл — это просто
22:47
номер с правами доступа. И на самой
22:49
вершине сидим мы. Если держать в голове
22:52
эту схему, магия исчезает. Остаётся
22:55
чистая, сухая логика. Больше не придётся
22:58
гуглить ошибки вслепую. Увидим проблему
23:01
Permission Dight и поймём, что это не
23:02
просто Linux абстракт на ругается, а это
23:05
ядро при выполнении Cisc Open, сверило
23:08
наш UID с битами в айноде и вернула код
23:10
ошибки. А когда сервер тормозит, то есть
23:13
высокий loadт average, мы понимаем, что
23:15
это не процессор устал, а это очередь
23:17
процессоров в планировщике стала слишком
23:19
длинной, и система тратит ресурсы на
23:21
переключение контекста. А когда нас
23:23
спрашивают про докер, мы улыбаемся,
23:25
потому что знаем, что нет никакого
23:27
докера. Есть просто грамотное
23:29
использование [музыка] неймспейсов и
23:30
сигрупсов, которые ядро предоставляет
23:32
любому процессу. Это и есть инженерное
23:35
мышление. Иникейщик учит команды
23:37
наизусть, а инженер понимает, как текут
23:39
байты. Команду можно нагуглить за 5
23:41
секунд, а понимание архитектуры
23:43
нагуглить нельзя, его можно только
23:45
наработать. И у нас в Телеге мы
23:47
подготовили для вас полную карту
23:49
архитектуры Linux одним пдфом. Там
23:51
расписаны основные сисколы, структура
23:53
файловой системы и этапы загрузки. Это
23:56
ваша шпаргалка, чтобы картинка всегда
23:58
была перед глазами. Забираете её в нашем
24:00
Телеграме, ссылка в описании.
24:02
Перестаньте быть просто пользователями,
24:04
становитесь инженерами, смотрите в
24:06
корень. И пока-пока.
24:10
По


