Линукс - удивительная ОС: не заразилась, 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]
Комментарии
Разве что все строки "в отличие от Windows" со смыслом "а там все НЕ так", я бы заменил - "в Windows все так же, но по-другому" :)))