Продолжая использовать наш сайт, вы даете согласие на обработку файлов cookie, которые обеспечивают правильную работу сайта. Благодаря им мы улучшаем сайт!
Принять и закрыть

Читать, слущать книги онлайн бесплатно!

Электронная Литература.

Бесплатная онлайн библиотека.

Читать: Внутреннее устройство Linux - Брайан Уорд на бесплатной онлайн библиотеке Э-Лит


Помоги проекту - поделись книгой:

4.5.1. Просмотр деталей дескрипторов inode

Чтобы увидеть значения дескриптора для любого каталога, используйте команду ls — i. Вот что получится, если применить ее к корневому каталогу нашего примера. Для получения более детальной информации воспользуйтесь командой stat.

$ ls — i

12 dir_1 7633 dir_2

Теперь вас, вероятно, заинтересует счетчик ссылок. Он уже встречался в результатах работы обычной команды ls — l. Как счетчик ссылок относится к файлам, показанным на рис. 4.5, и, в частности, к «жестко связанному» файлу file_5? Поле со счетчиком ссылок содержит общее количество записей в каталоге (по всем каталогам), которые указывают на дескриптор inode. У большинства файлов счетчик ссылок равен 1, поскольку они появляются лишь один раз среди записей каталога. Этого и следовало ожидать: в большинстве случаев при создании файла вы создаете новую запись в каталоге и соответствующий ей новый дескриптор inode. Однако дескриптор 15 появляется дважды: сначала он создан как дескриптор для файла dir_1/file_3, а затем связан с файлом dir_2/file_5. Жесткая ссылка является лишь созданной вручную записью в каталоге, связанной с уже существующим дескриптором inode. Команда ln (без параметра — s) позволяет вручную создавать новые ссылки.

По этой причине удаление файла иногда называется разъединением. Если запустить команду rm dir_1/file_2, ядро начнет поиск записи с именем file_2 в каталоге дескриптора inode 12. Обнаружив, что file_2 соответствует дескриптору inode 14, ядро удаляет эту запись из каталога, а затем вычитает 1 из счетчика ссылок для дескриптора inode 14. В результате этот счетчик ссылок становится равным 0 и ядро будет знать о том, что с данным дескриптором inode не связаны никакие имена. Следовательно, этот дескриптор и все относящиеся к нему данные можно удалить.

Однако, если запустить команду rm dir_1/file_3, в результате получится, что счетчик ссылок для дескриптора inode 15 изменится с 2 на 1 (поскольку ссылка dir_2/file_5 все еще указывает на него) и ядро узнает о том, что данный дескриптор не следует удалять.

Счетчик ссылок для каталогов устроен во многом так же. Заметьте, что счетчик ссылок дескриптора inode 12 равен 2, поскольку присутствуют две ссылки на этот дескриптор: одна для каталога dir_1 в записях каталога для дескриптора inode 2, а вторая ссылка в собственных записях каталога (.) ведет на саму себя. Если создать новый каталог dir_1/dir_3, счетчик ссылок для дескриптора inode 12 станет равным 3, поскольку новый катлог будет включать запись о родительском каталоге (..), который связан с дескриптором inode 12, подобно тому, как родительская ссылка дескриптора inode 12 указывает на дескриптор inode 2.

Есть одно небольшое исключение. У корневого дескриптора inode 2 счетчик ссылок равен 4. Однако на рис. 4.5 показаны только три ссылки на записи каталогов. «Четвертая» ссылка находится в суперблоке файловой системы, поскольку именно он указывает, где отыскать корневой дескриптор inode.

Не бойтесь экспериментировать со своей системой. Создание структуры каталогов с последующим применением команды ls — i или stat для исследования различных частей является безопасным. Вам не придется выполнять перезагрузку системы (если только вы не смонтировали новую файловую систему).

Тем не менее один фрагмент еще отсутствует: каким образом файловая система при назначении блоков из пула данных для нового файла узнает о том, какие блоки использованы, а какие свободны? Один из самых простых способов состоит в применении дополнительной структуры управления данными, которая называется битовой картой блоков. В этой схеме файловая система резервирует последовательность байтов, в которой каждый бит соответствует одному блоку в пуле данных. Если бит равен 0, это означает, что данный блок свободен, а если 1, то блок используется. Таким образом, в основу распределения блоков положено переключение состояния битов.

Проблемы в файловой системе возникают тогда, когда данные из таблицы дескрипторов inode не соответствуют данным о размещении блоков или когда счетчики ссылок неверные; это может произойти, если работа системы была завершена некорректно. Тогда при проверке файловой системы (как было рассказано в подразделе 4.2.11) команда fsck будет просматривать таблицу дескрипторов inode и структуру каталогов, чтобы определить новые счетчики ссылок и создать новую карту размещения блоков (такую как битовая карта блоков), после чего она сравнит только что созданные данные с файловой системой на диске. Если обнаружатся несоответствия, команда fsck должна исправить счетчики ссылок и определить, как поступить с теми дескрипторами inode и/или данными, которые не были обнаружены при просмотре структуры каталогов. Большинство команд fsck помещает такие «осиротевшие» новые файлы в каталог lost+found.

4.5.2. Работа с файловыми системами в пространстве пользователя

При работе с файлами и каталогами в пространстве пользователя вы можете не беспокоиться о том, как это реализовано на нижнем уровне. От вас ожидают, что доступ к содержимому файлов и каталогов смонтированной файловой системы будет осуществляться с помощью системных вызовов ядра. Любопытно, что при этом у вас все же есть доступ к определенной системной информации, которая не очень вписывается в пространство пользователя, в частности, системный вызов stat() возвращает номера дескрипторов inode и счетчики ссылок.

Если вы не заняты обслуживанием файловой системы, следует ли волноваться насчет дескрипторов inode и счетчиков ссылок? Как правило, нет. Эти данные доступны для команд из пространства пользователя в основном в целях обратной совместимости. К тому же не все файловые системы, доступные в Linux, располагают необходимой для них «начинкой». Слой интерфейса VFS обеспечивает то, что системные вызовы всегда возвращают значения дескрипторов inode и счетчиков ссылок, однако такие числа не обязаны что-либо значить.

В нетрадиционных файловых системах вы можете быть лишены возможности выполнять обычные для Unix операции с файловой системой. Например, нельзя использовать команду ln, чтобы создать жесткую ссылку в смонтированной файловой системе VFAT, поскольку в ней совершенно другая структура записей о каталогах.

Системные вызовы, которые доступны в пространстве пользователя Unix/Linux, обеспечивают достаточный уровень абстракции для безболезненного доступа к файлам: вам не обязательно знать что-либо о том, как он реализован, чтобы работать с файлами. Более того, гибкий формат имен файлов и поддержка использования разного регистра символов облегчают возможность применения других файловых систем с иерархической структурой.

Помните о том, что ядро не обязано поддерживать специфические файловые системы. В файловых системах с пространством пользователя ядро лишь выступает в роли проводника для системных вызовов.

4.5.3. Эволюция файловых систем

Даже в самой простой файловой системе имеется множество различных компонентов, требующих обслуживания. В то же время предъявляемые к файловым системам требования неуклонно возрастают по мере появления новых задач, технологий и возможностей хранения данных. Нынешний уровень производительности, целостности данных и требований безопасности намного превосходит ранние реализации файловых систем, поскольку технология файловых систем постоянно меняется. Мы уже упоминали в качестве примера о Btrfs — файловой системе нового поколения (см. подраздел 4.2.1).

Одним из примеров того, как изменяются файловые системы, является использование новыми файловыми системами раздельных структур данных для представления каталогов и имен файлов, а не дескрипторов inode, описанных здесь. Они по-другому ссылаются на блоки данных. Кроме того, в процессе развития находятся файловые системы, оптимизированные для дисков SSD. Постоянные изменения в развитии файловых систем являются нормой, однако имейте в виду, что эволюция файловых систем не изменяет их предназначения.

5. Как происходит загрузка ядра Linux

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

Упрощенная схема процесса загрузки выглядит так.

1. Система BIOS или прошивка загрузки загружают и запускают загрузчик системы.

2. Загрузчик системы отыскивает образ ядра на диске, загружает его в память и запускает.

3. Ядро выполняет инициализацию устройств и их драйверов.

4. Ядро монтирует корневую файловую систему.

5. Ядро запускает команду init с идентификатором процесса 1. Эта точка является началом пространства пользователя.

6. Команда init приводит в действие остальные системные процессы.

7. В определенный момент команда init запускает процесс, позволяющий вам войти в систему. Обычно это происходит в конце или незадолго до окончания загрузки системы.

В этой главе рассмотрены шаги с первого по четвертый, основное внимание уделено загрузчикам ядра и системы. В главе 6 продолжается рассказ о загрузке пространства пользователя.

Способность определять каждую стадию процесса загрузки окажется неоценимой, когда вам придется устранять проблемы при загрузке, а также поможет понять систему в целом. Однако принятый по умолчанию режим загрузки во многих версиях Linux зачастую затрудняет (если не делает невозможным) идентификацию некоторых первых этапов, и вам, вероятно, удастся посмотреть на них только по их завершении, после входа в систему.

5.1. Сообщения при запуске

Традиционные системы Unix во время загрузки выводят множество диагностических сообщений, чтобы проинформировать вас о ходе загрузки. Эти сообщения исходят сначала от ядра, а затем от процессов и процедур инициализации, которые запускает команда init. Однако такие сообщения не очень привлекательны и последовательны, а в некоторых случаях они даже не слишком информативны. В большинстве современных версий Linux стараются скрыть их с помощью экранов загрузки, заполнителя и параметров загрузки. Кроме того, улучшенные аппаратные средства привели к тому, что ядро загружается намного быстрее, чем раньше, поэтому сообщения проскакивают настолько быстро, что было бы трудно уяснить, что происходит.

Существуют два способа увидеть сообщения ядра о загрузке и оперативной диагностике. Вы можете:

• заглянуть в системный журнал ядра. Обычно он находится в файле /var/log/kern.log, но в зависимости от конфигурации вашей системы может также оказаться вместе с другими системными журналами в каталоге /var/log/messages или где-либо еще;

• воспользоваться командой dmesg, не забыв при этом указать параметр less, поскольку результаты займут намного больше места, чем один дисплей. Команда dmesg использует циклический буфер ядра, размер которого ограничен, но в большинстве новых версий ядра буфер достаточно велик, чтобы хранить сообщения в течение длительного времени.

Вот пример того, что можно ожидать в результате работы команды dmesg:

$ dmesg

[ 0.000000] Initializing cgroup subsys cpu

[ 0.000000] Linux version 3.2.0-67-generic-pae (buildd@toyol) (gcc version 4.

6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)) #101-Ubuntu SMP Tue Jul 15 18:04:54 UTC 2014

(Ubuntu 3.2.0-67.101-generic-pae 3.2.60)

[ 0.000000] KERNEL supported cpus:

— snip—

[ 2.986148] sr0: scsi3-mmc drive: 24x/8x writer dvd-ram cd/rw xa/form2 cdda tray

[ 2.986153] cdrom: Uniform CD-ROM driver Revision: 3.20

[ 2.986316] sr 1:0:0:0: Attached scsi CD-ROM sr0

[ 2.986416] sr 1:0:0:0: Attached scsi generic sg1 type 5

[ 3.007862] sda: sda1 sda2 < sda5 >

[ 3.008658] sd 0:0:0:0: [sda] Attached SCSI disk

— snip

Процедура запуска пространства пользователя часто оставляет сообщения после запуска ядра. Эти сообщения будет сложнее увидеть и просмотреть, поскольку в большинстве систем они не находятся в одном файле журнала. Сценарии запуска, как правило, выводят собщения в консоль, а по завершении процесса загрузки они стираются. Тем не менее это не является проблемой, поскольку каждый сценарий обычно ведет собственный журнал. Определенные версии команды init, например Upstart и systemd, способны перехватывать диагностические сообщения процесса загрузки и обычной работы, которые в обычном случае отображаются в консоли.

5.2. Инициализация ядра и параметры загрузки

Во время запуска ядро системы Linux выполняет инициализацию в следующем порядке.

1. Проверка центрального процессора.

2. Проверка оперативной памяти.

3. Обнаружение шины устройств.

4. Обнаружение устройств.

5. Настройка вспомогательной подсистемы ядра (сеть и т. п.).

6. Монтирование корневой файловой системы.

7. Запуск пространства пользователя.

Первые шаги не слишком примечательны, но зато, когда ядро добирается до устройств, возникает вопрос о зависимостях. Например, драйверы дисковых устройств могут зависеть от поддержки шины и подсистемы SCSI.

Далее в ходе инициализации ядро должно смонтировать корневую файловую систему до запуска команды init. Как правило, вам не придется беспокоиться об этих процессах, исключая тот случай, когда необходимые компоненты являются загружаемыми модулями ядра, а не частями основного ядра. На некоторых компьютерах вам может потребоваться загрузить такие модули ядра до монтирования реальной корневой файловой системы. Мы рассмотрим этот вопрос и обходные пути его решения в разделе 6.8.

На момент написания книги ядро не выводит каких-либо специальных сообщений, когда оно готово к запуску первого пользовательского процесса. Тем не менее приведенные ниже сообщения об управлении памятью являются верным признаком того, что скоро вступит в игру пространство пользователя, так как именно сейчас ядро защищает собственную память от процессов из пространства пользователя:

Freeing unused kernel memory: 740k freed

Write protecting the kernel text: 5820k

Write protecting the kernel read-only data: 2376k

NX-protecting the kernel data: 4420k

Вы можете также увидеть сообщение о том, что в данный момент происходит монтирование корневой файловой системы.

примечание

Можете спокойно переходить к главе 6, чтобы узнать об особенностях запуска пространства пользователя и команде init, которую ядро запускает в качестве первого процесса. Далее в данной главе приводятся подробности запуска ядра.

5.3. Параметры ядра

При запуске ядра Linux загрузчик передает ему набор текстовых параметров ядра, которые говорят ядру о том, как оно должно быть запущено. Эти параметры описывают различные варианты действий, такие как, например, величина выполняемого ядром диагностического вывода и варианты настроек, зависящие от драйверов устройств.

Параметры ядра при загрузке вашей системы можно увидеть в файле /proc/cmdline:

$ cat /proc/cmdline

BOOT_IMAGE=/boot/vmlinuz-3.2.0-67-generic-pae root=UUID=70ccd6e7-6ae6-44f6-

812c-51aab8036d29 ro quiet splash vt.handoff=7

Эти параметры являются либо простыми однословными флагами, вроде ro и quiet, либо парами key=value, например vt.handoff=7. Многие из этих параметров не являются существенными, например флаг splash, отвечающий за отображение экрана загрузки. Действительно важным является параметр root. Он задает местоположение корневой файловой системы, без него ядро не может отыскать команду init, а следовательно, и выполнить запуск пространства пользователя.

Корневая файловая система может быть определена как файл устройства, например так:

root=/dev/sda1

Однако в большинстве современных ПК более распространенным является применение идентификаторов UUID (см. подраздел 4.2.4):

root=UUID=70ccd6e7-6ae6-44f6-812c-51aab8036d29

Параметр ro стандартен; он указывает ядру на то, что корневую файловую систему при запуске пространства пользователя следует монтировать в режиме «только чтение». Этот режим гарантирует возможность безопасной проверки корневой файловой системы с помощью команды fsck. По окончании проверки процесс загрузки выполняет повторное монтирование корневой файловой системы в режиме «чтение-запись».

При обнаружении какого-либо непонятного параметра ядро Linux сохраняет его, а затем передает команде init при выполнении запуска пространства пользователя. Например, если вы добавите к параметрам ядра флаг — s, оно передаст его команде init, и это будет означать, что запуск следует выполнить в режиме одиночного пользователя.

Теперь рассмотрим механику того, как загрузчики системы запускают ядро.

5.4. Загрузчики системы

В начале процесса загрузки, до запуска ядра и команды init, загрузчик системы запускает ядро. Задача загрузчика системы выглядит просто: он загружает ядро в память, а затем запускает его с определенными параметрами. Рассмотрим вопросы, на которые должен ответить загрузчик системы.

• Где находится ядро?

• Какие параметры ядра должны быть переданы ему при запуске?

Ответ (как правило) такой: ядро и его параметры обычно располагаются в корневой файловой системе. Кажется, что параметры ядра отыскать несложно, но ведь само ядро еще не запущено, поэтому оно не может «пройтись» по файловой системе в поисках необходимых файлов. Кроме того, драйверы устройств, которые ядро обычно использует для доступа к диску, также недоступны. Можно увидеть в этом нечто вроде проблемы «яйцо или курица».

Начнем разбираться с драйверами. На персональных компьютерах загрузчики системы используют систему BIOS или интерфейс UEFI, чтобы получить доступ к дискам. Практически все дисковые аппаратные средства снабжаются прошивками, которые позволяют системе BIOS получать доступ к присоединенным устройствам хранения с помощью блочной адресации LBA (Linear Block Addressing). Хотя производительность этого режима невысока, он все же позволяет получить универсальный доступ к дискам. Загрузчики системы часто являются единственными программами, которые используют систему BIOS для доступа к дискам; ядро применяет собственные высокопроизводительные драйверы.



Поделиться книгой:

На главную
Назад