Файл: Debian Таненбаум Бос.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Операционные системы

Добавлен: 29.10.2018

Просмотров: 48094

Скачиваний: 190

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

10.2. Обзор системы Linux   

801

Рассмотрим несколько примеров этих утилит, начиная с программ для управления 
файлами и каталогами. Команда

cp a b

копирует файл 

a

 в 

b

, не изменяя исходный файл. Команда

mv a b

напротив, копирует файл 

a

 в 

b

, но удаляет исходный файл. В результате она не копи-

рует файл, а перемещает его. Несколько файлов можно сцепить в один при помощи 
команды cat, считывающей все входные файлы и копирующей их один за другим 
в стандартный выходной поток. Удалить файлы можно командой rm. Команда chmod 
позволяет владельцу изменить права доступа к файлу. Каталоги можно создать коман-
дой mkdir и удалить командой rmdir. Список файлов можно увидеть при помощи 
команды ls. У этой команды множество флагов, управляющих видом формируемого 
ею листинга. При помощи одних флагов можно задать, насколько подробно будет 
отображаться каждый файл (размер, владелец, группа, дата создания), другими фла-
гами задается порядок, в котором перечисляются файлы (по алфавиту, по времени 
последнего изменения, в обратном порядке), третья группа флагов позволяет задать 
расположение списка файлов на экране и т. д.

Мы уже рассматривали несколько фильтров: команда grep извлекает из стандартного 
входного потока (или из одного или нескольких файлов) строки, содержащие задан-
ную последовательность символов; команда sort сортирует входной поток и выводит 
данные в стандартный выходной поток; команда head извлекает первые несколько 
строк; команда tail, напротив, выдает на выход указанное количество последних строк. 
Кроме того, стандартом 1003.2 определены такие фильтры, как cut и paste, которые 
позволяют вырезать из файлов и вставлять в файлы куски текста, команда od конвер-
тирует (обычно двоичный) вход в ASCII-строку (в восьмеричный, десятичный или 
шестнадцатеричный формат), команда tr преобразует символы (например, из нижнего 
регистра в верхний), а команда pr форматирует выход для вывода на принтер, позволяя 
добавлять заголовки, номера страниц и т. д.

Компиляторы и программные средства включают в себя компилятор gcc с языка C 
и программу ar, собирающую библиотечные процедуры в архивные файлы.

Еще одним важным инструментом является команда make, используемая для сборки 
больших программ, исходный текст которых состоит из множества файлов. Как пра-
вило, некоторые из этих файлов представляют собой заголовочные файлы (header 
files) , содержащие определения типов, переменных, макросов и прочие декларации. 
Исходные файлы обычно ссылаются на эти файлы с помощью специальной директивы 
include. Таким образом, два и более исходных файла могут совместно использовать одни 
и те же декларации. Однако если файл заголовков изменен, то необходимо найти все 
исходные файлы, зависящие от него, и перекомпилировать их. Задача команды make 
заключается в том, чтобы отслеживать, какой файл от какого заголовочного файла 
зависит, и автоматически запускать компилятор для тех файлов, которые требуется 
перекомпилировать. Почти все программы в системе Linux, кроме самых маленьких, 
компилируются с помощью команды make.

Часть команд POSIX перечислена в табл. 10.1 вместе с кратким описанием. Во всех 
версиях операционной системы Linux есть эти программы, а также многие другие.


background image

802  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

Таблица 10.1. Некоторые утилиты Linux, требуемые стандартом POSIX

Программа

Функция

cat

Конкатенация нескольких файлов в стандартный выходной поток

chmod

Изменение режима защиты файла

cp

Копирование файлов

cut

Вырезание колонок текста из файла

grep

Поиск определенного шаблона в файле

head

Извлечение из файла первых строк

ls

Распечатка каталога

make

Компиляция файлов для создания двоичного файла

mkdir

Создание каталога

od

Восьмеричный дамп файла

paste

Вставка колонок текста в файл

pr

Форматирование файла для печати

rm

Удаление файлов

rmdir

Удаление каталога

sort

Сортировка строк файла по алфавиту

tail

Извлечение из файла последних строк

tr

Преобразование символов из одного набора в другой

10.2.5. Структура ядра

На рис. 10.1 была показана общая структура системы Linux  . Давайте теперь подробнее 
рассмотрим ядро системы (перед тем как начать изучение планирования процессов 
и файловой системы).

Ядро работает непосредственно с аппаратным обеспечением и обеспечивает взаимодей-
ствие с устройствами ввода-вывода и блоком управления памятью, а также управляет 
доступом процессора к ним. Нижний уровень ядра (рис. 10.2) состоит из обработчиков 
прерываний (которые являются основным средством взаимодействия с устройствами) 
и механизма диспетчеризации на низком уровне. Диспетчеризация производится при 
возникновении прерывания. При этом код низкого уровня останавливает выполнение 
работающего процесса, сохраняет его состояние в структурах процессов ядра и запуска-
ет соответствующий драйвер. Диспетчеризация процессов производится также тогда, 
когда ядро завершает некую операцию и пора снова запустить процесс пользователя. 
Код диспетчеризации написан на ассемблере и представляет собой отдельную от про-
цедуры планирования программу. 

Затем мы разделили различные подсистемы ядра на три основных компонента. Ком-
понент ввода-вывода на рис. 10.2 содержит все те части ядра, которые отвечают за 
взаимодействие с устройствами, а также выполнение сетевых операций и операций 
ввода-вывода на внешние устройства. На самом высоком уровне все операции ввода-
вывода интегрированы в уровень виртуальной файловой системы (Virtual File System 
(VFS)). То есть на самом верхнем уровне выполнение операции чтения из файла (будь 
он в памяти или на диске) — это то же самое, что и выполнение операции чтения симво-
ла с терминального ввода. На самом низком уровне все операции ввода-вывода прохо-
дят через какой-то драйвер устройства. Все драйверы в Linux классифицируются либо


background image

10.2. Обзор системы Linux   

803

Рис. 10.2. Структура ядра операционной системы Linux

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

Выше уровня драйверов устройств код ядра для каждого типа устройств свой. Сим-
вольные устройства могут использоваться двумя разными способами. Некоторым 
программам, таким как экранные редакторы vi и emacs, требуется каждая нажатая 
клавиша без какой-либо обработки. Для этого служит необработанный ввод-вывод 
с терминала (tty). Другое программное обеспечение (такое, как оболочки) принимает 
на входе уже готовую текстовую строку, позволяя пользователю редактировать ее, пока 
не будет нажата клавиша 

Enter

 для отправки строки в программу. В этом случае поток 

символов с устройства терминала передается через так называемую дисциплину линии 
связи (и применяется соответствующее форматирование).

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


background image

804  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

Над дисковыми драйверами располагается планировщик ввода-вывода, который от-
вечает за упорядочивание и выдачу запросов на дисковые операции таким способом, 
который экономит излишние перемещения головок (или реализует некую иную си-
стемную стратегию).

На самом верху столбца блочных устройств располагаются файловые системы. Linux 
имеет несколько одновременно сосуществующих файловых систем. Для того чтобы 
скрыть «страшные» архитектурные отличия аппаратных устройств от реализации фай-
ловой системы, уровень обобщенных блочных устройств обеспечивает используемую 
всеми файловыми системами абстракцию.

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

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

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

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

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

10.3. Процессы в системе Linux

В предыдущих разделах мы начали наш обзор системы Linux с точки зрения пользо-
вателя, сидящего за клавиатурой (то есть с того, что видит пользователь в окне 

xterm

). 

Были приведены примеры часто использующихся команд оболочки и утилит. Этот 
краткий обзор был завершен рассмотрением структуры системы. Теперь настало время 


background image

10.3. Процессы в системе Linux   

805

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

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

10.3.1. Фундаментальные концепции

Основными активными сущностями в системе Linux являются процессы. Процессы 
Linux очень похожи на классические последовательные процессы, которые мы изу-
чали в главе 2. Каждый процесс выполняет одну программу и изначально получает 
один поток управления. Иначе говоря, у процесса есть один счетчик команд, который 
отслеживает следующую исполняемую команду. Linux позволяет процессу создавать 
дополнительные потоки (после того, как он начинает выполнение).

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

Типичным демоном является cron. Он просыпается раз в минуту, проверяя, не нужно 
ли ему что-то сделать. Если у него есть работа, он ее выполняет, а затем отправляется 
спать дальше (до следующей проверки).

Этот демон позволяет планировать в системе Linux активность на минуты, часы, дни 
и даже месяцы вперед. Например, представьте, что пользователю назначено явиться 
к зубному врачу в 15.00 в следующий вторник. Он может создать запись в базе данных 
демона cron, чтобы тот просигналил ему, скажем, в 14.30. Когда наступают назначенные 
день и время, демон cron видит, что у него есть работа, и в нужное время запускает про-
грамму звукового сигнала (в виде нового процесса).

Демон cron также используется для периодического запуска задач, например ежеднев-
ного резервного копирования диска в 4.00 или напоминания забывчивым пользователям 
каждый год 31 октября купить новые «страшненькие» товары для веселого празднования 
Хэллоуина. Другие демоны управляют входящей и исходящей электронной почтой, 
очередями принтера, проверяют, достаточно ли еще осталось свободных страниц па-
мяти, и т. д. Демоны реализуются в системе Linux довольно просто, так как каждый из 
них представляет собой отдельный процесс, не зависимый от всех остальных процессов.

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

 (parent process)  . Новый процесс называется дочерним процессом (child 

process)  . У родительского и у дочернего процессов есть собственные (приватные) об-