Этот занятный Линукс

Линукс - удивительная ОС: не заразилась, 2 года работая без антивируса в Интернете, приходит в рабочее состояние чрезвычайно быстро. Но самое приятное - изучение её внутреннего устройства доступнее, чем изучение Windows. Кто-то скажет: "Зачем изучать, надо работать!", - и будет прав, моя жена так и поступает. Но чтобы понять философию Линукса, надо взглянуть на него изнутри.


Основа - ядро

Стабильность Линуксу обеспечивает его ядро - единственный процесс, который напрямую работает с "железом", все остальные процессы имеют доступ к "железу" только через него. Ядро содержит подсистему виртуальной памяти, планировщик задач, виртуальную файловую систему (ФС) и драйверы "железа". Графической системы в ядре НЕТ! Но об этом отдельно и не в этой статье. Первоначально ядро было монолитным, т.е. содержало все прикомпилированные драйверы, и добавить/убавить что-либо было невозможно. Сейчас ядро имеет только необходимые драйверы, которые называют статическими, а остальные драйверы - динамические - подгружаются по мере необходимости. Эта особенность способствует скорости загрузки Линукса, хотя и замедляет первоначальную загрузку приложений, по сравнению с Windows.

В настоящее время ядро и его модули снабжены цифровыми подписями и защищены от сторонних модулей, которые вредонос мог бы попытаться загрузить. Версию ядра легко узнать терминальной командой uname -r. Образ ядра находится в директории /boot в файле vmlinuz-<версия>, а загружаемые модули хранятся в директории /lib/modules/<версия_ядра>, там же лежит и таблица зависимостей между модулями. Во время работы ядро использует счётчики ссылок на динамические модули. Если модуль кем-либо востребован, то счётчик ссылок на этот модуль инкрементируется, иначе декрементируется. Если счётчик ссылок не нулевой, то модуль остаётся загруженным, иначе выгружается. Таким гениальным по простоте способом ядро разрешает межмодульные зависимости и экономит память, что позволяет Линуксу всячески избегать подкачки страниц и работать на слабых машинах эффективнее, чем это делает Windows.

Однако загрузиться ядро самостоятельно не может: для загрузки требуется работающая ФС с драйверами, но они - часть ядра. Помогает загрузчик GRUB, который BIOS'ом считывается с MBR-носителя, являющегося загрузочным, с точки зрения BIOS'а, и которому BIOS передаёт управление. Далее GRUB допрочитывает свой код и интересуется у пользователя, какую ОС грузить. Если GRUB'у указать, что загрузить следует Windows, то он передаст управление загрузчику Windows. Однако автор убеждён, что лучше всего устанавливать Линукс на отдельный привод и позволить инсталлятору устанавливать GRUB на этот же привод, что впоследствии позволит грузить Windows без GRUB'а напрямую, например, через нажатие определённой функциональной клавиши (у автора это F12) с последующим указанием, с какого привода грузить ОС. Кроме того, при таком подходе можно экспериментировать с Линуксом сколько угодно, не опасаясь повредить ОС Windows.


Виртуальная память

Подсистема виртуальной памяти распределяет ресурс между программами (процессами), управляет подкачкой и кэшированием страниц. Каждой программе выделяется 4 Гб виртуальной памяти страницами по 4 кБ, но реально программа занимает тот объем, с которым работает. Выделение страницы ОЗУ программе называют отображением страницы в адресное пространство программы.

При обращении программы к странице адресного пространства ядро проверяет права доступа к этой странице и при успехе переадресовывает обращение на реальный адрес этой страницы, иначе выгружает одну из наиболее долго не использовавшихся страниц ОЗУ в файл подкачки. Это традиционно называют свопингом. При запуске новой программы ядро пытается найти свободную страницу ОЗУ, иначе также "свопит". Однако Линукс умеет экономить: позволяет разным программам создавать общие сегменты памяти для обмена данными. Эти сегменты относятся к объектам межпроцессной связи, к ним также относятся семафоры и очереди сообщений. Посмотреть список всех таких объектов можно командой ipcs. Кстати, перед повторным запуском зависшей программы командой ipcrm следует удалить все старые объекты межпроцессного взаимодействия, оставшиеся неосвобождёнными, иначе вновь запущенная программа не сможет их создать.

В норме все программы, загруженные в компьютер, в т.ч. и закрытые пользователем, кэшируются в виртуальной памяти. В современных компьютерах с достаточно большим ОЗУ (2 Гб и больше) файл подкачки практически не используется. Однажды загруженная и закрытая программа повторно запустится намного быстрее, чем в первый раз. Посмотреть расход виртуальной памяти можно командой free.

mike@mike:~$ free
             total    used    free shared buffers cached
Mem:       2071684 1600968  470716      0  120384 744820
-/+ buffers/cache:  735764 1335920
Swap:      4152688       0 4152688

В данном примере 120384 + 744820 + 735764 = 1600968 килобайт = использованная память, однако 735764 килобайт приходятся на закрытые приложения, поэтому фактически свободная память составляет 1335920 килобайт: 2071684 - 735764 = 1335920. Т.е., ОЗУ использовано на 35%, а не на 77%, как можно было бы подумать, глядя на строку Mem.


Виртуальная ФС

Фишка Линукса - операция монтирования. Суть её состоит в связывании некоторого каталога ("точка монтирования") с устройством и драйвером ФС. Для этого ядро передает драйверу ФС ссылку на устройство, и если драйвер его опознал, то ядро заносит в таблицу монтирования информацию о том, что все каталоги-файлы, чей путь начинается с указанной точки монтирования, обслуживаются данным драйвером и расположены на данном устройстве. Кроме виртуальной ФС, Линукс имеет ещё кучу разных ФС. Список можно посмотреть в файле /proc/filesystems, а таблицу примонтированных ФС - командой cat /proc/mounts. Дело в том, что ядро генерирует информацию о своем состоянии и хранит ее в директории /proc. Содержимое /proc создаётся в RAM при каждом запуске системы и переписывается в /proc. Контролируется /proc только ядром.

В виртуальной ФС имеются разные типы файлов: обычные файлы, каталоги, каналы, символьные ссылки, жёсткие ссылки, сокеты и специальные файлы.

Каталог - это список имён группы файлов. Современному пользователю Линукса вовсе не обязательно знать терминальные команды cd, ls, touch, cp, mv, rm, mkdir, chown, chmod, chgrp, mount, umount (о них "Вести" уже писали) и др., так как к ним во многих дистрибутивах прилагается графический фронтенд под общим названием "обозреватель", позволяющий обходиться без этих знаний.

Каналы являются буферами обмена между приложениями, а сокет объединяет несколько буферов. Именованный канал "вручную" создаётся командой mkfifo <имя>, а неименованный устанавливается с помощью символа "|". Разумеется, каналы могут создаваться и уничтожаться из программ. С каналом работают как с обычным файлом, но он не сохраняет данные, и в канал нельзя писать новые данные, если не прочитаны предыдущие.

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

Жёсткая ссылка - это псевдоним файла в пределах одной и той же ФС. Файл, на который имеется жёсткая ссылка, удалить невозможно. По умолчанию команда ln <имя файла> создаёт жёсткую ссылку; для создания символьной ссылки перед именем файла нужна опция -s.


Устройства представлены файлами!

Специальные файлы - это другая большая фишка Линукса. Они расположены в каталоге /dev. Эти файлы служат точками, через которые идёт обращение к драйверам соответствующих им устройств. У каждого такого файла есть три характеристики - тип устройства (символьное "с" или блочное "b"), номер строки (мажор) и номер столбца (минор) таблицы ссылок на драйверы устройств. Символьное устройство обменивается с другими устройствами отдельными байтами, блочное - блоками байт. Ядро хранит две таблицы ссылок: для символьных и для блочных устройств. Мажор обязательно соответствует определённому типу устройства, например, для символьных устройств это COM-порты, LPT-порты, PS/2-мыши, USB-мыши и т.д., для блочных устройств это SCSI-диски, IDE-диски, SCSI-CD-приводы, RAID-контролеры и т.п. Рассмотрим дисковое хозяйство, так как понимание его упрощает и резервное копирование, и наращивание системы.


Дисковая подсистема

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

Контроллер Канал Режим Файл
1 1 primary master /dev/hda
1 1 primary slave /dev/hdb
1 2 secondary master /dev/hdc
1 2 secondary slave /dev/hdd

Разделы в Линуксе принято обозначать не буквами, а цифрами. Диски SATA обозначаются аналогично: sda, sdb и т.д. Шина SATA по своей логике похожа на SCSI. В моём компьютере установлены разные накопители: и IDE, и SATA. Однако я был очень удивлён, когда после перехода с Убунту 7.04 на Убунту 8.10 обнаружил, что IDE-диск тоже виден как SCSI! Оказывается, новые ядра работают с IDE-дисками через подсистему SCSI, и теперь все диски, включая CD/DVD приводы, представляются как SCSI-устройства.

mike@mike:~$ ls -lL /dev/sd*
brw-rw---- 1 root disk 8,  0 2009-06-09 10:01 /dev/sda
brw-rw---- 1 root disk 8,  1 2009-06-09 10:01 /dev/sda1
brw-rw---- 1 root disk 8,  2 2009-06-09 10:01 /dev/sda2
brw-rw---- 1 root disk 8,  5 2009-06-09 10:01 /dev/sda5
brw-rw---- 1 root disk 8,  6 2009-06-09 10:01 /dev/sda6
brw-rw---- 1 root disk 8,  7 2009-06-09 10:01 /dev/sda7
brw-rw---- 1 root disk 8, 16 2009-06-09 10:01 /dev/sdb
brw-rw---- 1 root disk 8, 17 2009-06-09 10:01 /dev/sdb1
brw-rw---- 1 root disk 8, 18 2009-06-09 10:01 /dev/sdb2
brw-rw---- 1 root disk 8, 21 2009-06-09 10:01 /dev/sdb5
brw-rw---- 1 root disk 8, 22 2009-06-09 10:01 /dev/sdb6
brw-rw---- 1 root disk 8, 32 2009-06-09 10:01 /dev/sdc
brw-rw---- 1 root disk 8, 33 2009-06-09 07:01 /dev/sdc1
brw-rw---- 1 root disk 8, 34 2009-06-09 10:01 /dev/sdc2
brw-rw---- 1 root disk 8, 37 2009-06-09 10:01 /dev/sdc5
brw-rw---- 1 root disk 8, 38 2009-06-09 07:01 /dev/sdc6
brw-rw---- 1 root disk 8, 39 2009-06-09 10:01 /dev/sdc7

Из листинга следует, что в компьютере установлено 3 накопителя, каждый из которых может содержать до 15 разделов (16-й - контроллер накопителя). Минор контроллера накопителя по модулю 16 всегда нулевой, а мажор всегда равен 8 и совершенно не зависит от раздела. Поэтому, если выключить компьютер и физически отключить первый накопитель, то после перезагрузки второй накопитель, который был sdb, станет sda, а sdc станет sdb. Данные по команде ls доступны всем пользователям, но не слишком информативны. Детальную информацию о дисках можно извлечь командой fdisk на правах суперпользователя.

mike@mike:~$ sudo fdisk -l
[sudo] password for mike: ******
Диск /dev/sda: 80.0 ГБ, 80060424192 байт
255 heads, 63 sectors/track, 9733 cylinders
Units = цилиндры of 16065 * 512 = 8225280 bytes
Disk identifier: 0x359f359f
Устр-во Загр Начало  Конец      Блоки  Id Система
/dev/sda1  *      1    136    1092388+  b W95 FAT32
/dev/sda2       137   9733   77087902+  f W95 расшир. (LBA)
/dev/sda5       137   4244   32997478+ 83 Linux
/dev/sda6      4245   4506    2104483+ 82 Linux своп / Solaris
/dev/sda7      4507   9733    41985846  b W95 FAT32

Диск /dev/sdb: 200.0 ГБ, 200049647616 байт
255 heads, 63 sectors/track, 24321 cylinders
Units = цилиндры of 16065 * 512 = 8225280 bytes
Disk identifier: 0xef0001d0
Устр-во Загр Начало  Конец      Блоки  Id Система
/dev/sdb1  *      1   1913   15366141   7 HPFS/NTFS
/dev/sdb2      1914  24321  179992260   f W95 расшир. (LBA)
/dev/sdb5      1914   5101  25607578+   7 HPFS/NTFS
/dev/sdb6      5102  24321  54384618+   7 HPFS/NTFS

Диск /dev/sdc: 160.0 ГБ, 160041885696 байт
16 heads, 63 sectors/track, 310101 cylinders
Units = цилиндры of 1008 * 512 = 516096 bytes
Disk identifier: 0xf5195452
Устр-во Загр Начало  Конец      Блоки  Id Система
/dev/sdc1  *      1    520    262048+  83 Linux
/dev/sdc2       521 309346  155648304   f W95 расшир. (LBA)
/dev/sdc5       521 224012 112639936+   7 HPFS/NTFS
/dev/sdc6    224013 305282  40960048+  83 Linux
/dev/sdc7    305283 309346   2048224+  82 Linux своп / Solaris

По вышеприведенным данным совсем просто разобраться, что собой представляет дисковое хозяйство компьютера. Современным пользователям нет необходимости прибегать к услугам команды fdisk; для них есть графические фронтенды (в Ubuntu это gparted, запуск которого даёт ещё более наглядное представление о дисковом хозяйстве). Вообще-то эти графические фронтенды являются аналогами легендарного "Partition Magic" для Windows. Теоретически ядро поддерживает до 4096 SCSI-дисков, что для пользователей более чем достаточно.


Сделаете то же в Windows?

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

mike@mike:~$ cd /dev
mike@mike:/dev$ ls -l dev/sda14
ls: невозможно получить доступ к dev/sda14: No such file or directory

Однако попробуем создать спецфайл для него как для блочного устройства с мажором 8 и минором 14:

mike@mike:/dev$ sudo mknod sda14 b 8 14
[sudo] password for mike: ******
mike@mike:/dev$ ls -l /dev/sda14
brw-r--r-- 1 root root 8, 14 2009-06-10 17:20 /dev/sda14

Получилось! Но такого реального устройства нет, что можно проверить, попытавшись замечательной командой dd (я ею пользуюсь для бэкапа) посекторно отправить раздел sda14 в заведомо существующую "чёрную дыру" как устройство, представленное файлом /dev/null:

mike@mike:/dev$ sudo dd if=sda14 of=/dev/null
[sudo] password for mike: ******
dd: открытие `sda14': No such device or address

Здесь if - это input file, of - output file, а вовсе не английские слова. Ответ: нет устройства sda14!

Кроме "чёрной дыры", в Линуксе есть и другие экзотические отсутствующие устройства, которые тоже работают! Например, /dev/random и /dev/zero. Как можно догадаться, первое выдаёт случайный бред, а второе - нули. Попробуйте, например, на правах суперпользователя заставить систему выполнить такую команду:

$ sudo dd if=/dev/random of=/dev/sda6 

Не исключено, что Линукс поинтересуется, всё ли в порядке у вас с устройством /dev/brain. Шутка, конечно; забивать основной раздел случайными байтами пробовать не стоит. Однако резонно спросить: а зачем в Линуксе возможность создания специальных файлов для несуществующих устройств? Об этом в следующий раз, хотя для внимательного читателя ответ частично содержится и в этой статье.

Михаил ГУРЧИК,
[email protected]

Версия для печатиВерсия для печати

Номер: 

39 за 2010 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Savely
Что-то я это статьи не видел... Нормально так.

Разве что все строки "в отличие от Windows" со смыслом "а там все НЕ так", я бы заменил - "в Windows все так же, но по-другому" :)))

Аватар пользователя mike
Спасибо, Savely. И замечание хорошее -- по делу и c юмором.