Модель файловой системы Linux/Unix — КиберПедия 

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

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

Модель файловой системы Linux/Unix

2021-01-29 107
Модель файловой системы Linux/Unix 0.00 из 5.00 0 оценок
Заказать работу

 

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

Поиск простоты направлялся двумя факторами. С технической точки зрения, первоначальные мини‑компьютеры PDP‑11, на которых разрабатывалась Unix, имели маленькое адресное пространство: 64 килобайта на меньших системах, 64 Кб кода и 64 Кб данных на больших. Эти ограничения относились не только к обычным программам (так называемому коду уровня пользователя), но и к самой операционной системе (коду уровня ядра). Поэтому не только «Маленький – значит красивый» в эстетическом смысле, но «Маленький – значит красивый», потому что не было другого выбора!

Вторым фактором была отрицательная реакция на современные коммерческие операционные системы, которые были без надобности усложнены, со сложными командными языками, множеством разновидностей файлового ввода‑вывода и слабой общностью или гармонией. (Стив Джонсон однажды заметил: «Использование TSO подобно пинанию мертвого кита на побережье». TSO – это как раз одна из только что описанных бестолковых систем с разделением времени «для мэйнфреймов.)

 

Файлы и права доступа

 

Файловая модель Unix проста, как фраза: файл – это линейный поток байтов. Точка. Операционная система не накладывает на файлы никаких предопределенных структур, ни фиксированных или переменных размеров записей, ни индексированных файлов, ничего. Интерпретация содержимого файла целиком оставлена приложению. (Это не совсем верно, как мы вскоре увидим, но для начала достаточно близко к истине.)

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

Unix разрабатывался для мини‑компьютеров с разделением времени; это предполагает наличие с самого начала многопользовательского окружения. Раз есть множество пользователей, должно быть возможным указание прав доступа к файлам: возможно, пользователь является начальником пользователя, и не хочет, чтобы прочел последние результаты аттестации.

В целях создания прав доступа пользователи подразделяются на три различные категории: владелец файла; группа пользователей, связанная с данным файлом (вскоре будет пояснено); и остальные пользователи. Для каждой из этих категорий каждый файл имеет отдельные, связанные с этим файлом, биты прав доступа, разрешающие чтение, запись и исполнение. Эти разрешения отображаются в первом поле вывода команды '':

ls ‑l progex.texi

 

Здесь arnold и devel являются соответственно владельцем и группой файла, a является строкой типа файла и прав доступа. Для обычного файла первым символом будет дефис, для каталогов ‑, а для других видов файлов ‑ небольшой набор других символов, которые пока не имеют значения. Каждая последующая тройка символов представляют права на чтение, запись и исполнение для владельца, группы и «остальных» соответственно.

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

Владелец и группа файла хранятся в виде числовых значений, известных как идентификатор пользователя (user ID – UID) и идентификатор группы (group ID – GID); стандартные библиотечные функции, которые мы рассмотрим далее в книге, позволяют напечатать эти значения в виде читаемых имен.

Владелец файла может изменить разрешения, используя команду (change mode – изменить режим). (Права доступа к файлу, по существу, иногда называют «режимом файла».) Группу файла можно изменить с помощью команд (change group – изменить группу) и (change owner – сменить владельца)[11].

Групповые права доступа были нацелены на поддержку совместной работы: хотя определенным файлом может владеть один член группы или подразделения, возможно, каждый член группы должен иметь возможность изменять его. (Рассмотрите совместный маркетинговый доклад или данные исследования.)

Когда система проверяет доступ к файлу (обычно при открытии файла), если UID процесса совпадает с UID файла, используются права доступа владельца файла. Если эти права доступа запрещают операцию (скажем, попытка записи в файл с доступом), операция завершается неудачей; Unix и Linux не продолжают проверку прав доступа для группы и других пользователей[12]. Это верно также, если UID различаются, но совпадают GID; если права доступа группы запрещают операцию, она завершается неудачей.

Unix и Linux поддерживают понятие суперпользователя (superuser): это пользователь с особыми привилегиями. Этот пользователь известен как root и имеет UID, равный 0. root позволено делать все; никаких проверок, все двери открыты, все ящики отперты.[13] (Это может иметь важные последствия для безопасности, которых мы будем касаться по всей книге, но не будем освещать исчерпывающе.) Поэтому, даже если файл имеет режим, все равно может читать файл и записывать в него. (Исключением является то, что файл нельзя исполнить. Но поскольку может добавить право на исполнение, это ограничение ничего не предотвращает.)

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

 

Каталоги и имена файлов

 

Раз у вас есть файл, нужно где‑то его хранить. В этом назначение каталога (известного в системах Windows или Apple Macintosh под названием «папка»). Каталог является особой разновидностью файла, связывающего имена файлов с метаданными, известными как узлы (inodes). Каталоги являются особыми, поскольку их может обновлять лишь операционная система путем описанных в главе 4, «Файлы и файловый ввод‑вывод», системных вызовов. Они особые также потому, что операционная система предписывает формат элементов каталога.

Имена файлов могут содержать любой 8‑битный байт, за исключением символа '' (прямой косой черты) и ASCII символа NUL, все биты которого содержат 0. Ранние Unix‑ системы ограничивали имена 14 байтами; современные системы допускают отдельные имена файлов вплоть до 255 байтов.

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

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

 

ЗАМЕЧАНИЕ. Если у вас есть разрешение на запись в каталог, вы можете удалять файлы из этого каталога, даже если они не принадлежат вам! При интерактивной работе команда rm отмечает это, запрашивая в таком случае подтверждение

Каталог имеет разрешение на запись для каждого, но ваши файлы в  находятся вполне в безопасности, поскольку обычно имеет установленный так называемый «липкий» (sticky) бит:

ls ‑ld /trap

 

Обратите внимание, что t находится в последней позиции первого поля. В большинстве каталогов в этом месте стоит x. При установленном «липком» бите ваши файлы можете удалять лишь вы, как владелец файла, или. (Более детально это обсуждается в разделе 11.2 5, «Каталоги и липкий бит».)

 

 

Исполняемые файлы

 

Помните, мы говорили, что операционная система на накладывает структуру на файлы? Мы уже видели, что это было невинной ложью относительно каталогов. Это же относится к двоичным исполняемым файлам. Чтобы запустить программу, ядро должно знать, какая часть файла представляет инструкции (код), а какая – данные. Это ведет к понятию формата объектного файла, которое определяет, как эти данные располагаются внутри файла на диске.

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

Поскольку компилятор, ассемблер и загрузчик являются инструментами режима пользователя, изменить со временем по мере необходимости форматы объектных файлов (сравнительно) просто; надо только «научить» ядро новому формату, и он может быть использован. Часть ядра, загружающая исполняемые файлы, относительно невелика, и это не является невозможной задачей. Поэтому форматы файлов Unix развиваются с течением времени. Первоначальный формат был известен как a.out (Assembler OUTput – вывод сборщика). Следующий формат, до сих пор использующийся в некоторых коммерческих системах, известен как COFF (Common Object File Format – общий формат объектных файлов), а современный, наиболее широко использующийся формат – ELF (Extensible Linking Format – открытый формат компоновки). Современные системы GNU/Linux используют ELF.

Ядро распознает, что исполняемый файл содержит двоичный объектный код, проверяя первые несколько байтов файла на предмет совпадения со специальными магическими числами. Это последовательности двух или четырех байтов, которые ядро распознает в качестве специальных. Для обратной совместимости современные Unix‑системы распознают несколько форматов. Файлы ELF начинаются с четырех символов «».

Помимо двоичных исполняемых файлов, ядро поддерживает также исполняемые сценарии (скрипты). Такой файл также начинается с магического числа: в этом случае, это два обычных символа. Сценарий является программой, исполняемой интерпретатором, таким, как командный процессор, awk, Perl, Python или Tcl. Строка, начинающаяся с, предоставляет полный путь к интерпретатору и один необязательный аргумент:

 

 

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

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

 

Устройства

 

Одним из самых замечательных новшеств Unix было объединение файлового ввода‑ вывода и ввода‑вывода от устройств.[14] Устройства выглядят в файловой системе как файлы, для доступа к ним используются обычные права доступа, а для их открытия, чтения, записи и закрытия используются те же самые системные вызовы ввода‑вывода. Вся «магия», заставляющая устройства выглядеть подобно файлам, скрыта в ядре. Это просто другой аспект движущего принципа простоты в действии, мы можем выразить это как никаких частных случаев для кода пользователя.

В повседневной практике, в частности, на уровне оболочки, часто появляются два устройства: и.

 является «битоприемником». Все данные, посылаемые, уничтожаются операционной системой, а все попытки прочесть отсюда немедленно возвращают конец файла (EOF).

 является текущим управляющим терминалом процесса – тем, который он слушает, когда пользователь набирает символ прерывания (обычно CTRL‑C) или выполняет управление заданием (CTRL‑Z).

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

Другие устройства представляют реальное оборудование, такое, как ленточные и дисковые приводы, приводы CD‑ROM и последовательные порты. Имеются также программные устройства, такие, как псевдотерминалы, которые используются для сетевых входов в систему и систем управления окнами, представляет системную консоль, особое аппаратное устройство мини‑компьютеров. В современных компьютерах представлен экраном и клавиатурой, но это может быть также и последовательный порт

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

ls ‑l /dev/tty /dev/hda

 

 

Начальная '' представляет блочные устройства, а '' представляет символьные устройства. Файлы устройств обсуждаются далее в разделе 5.4, «Получение информации о файлах».

 

 

Модель процессов Linux/Unix

 

Процесс является работающей программой.[15] Процесс имеет следующие атрибуты:

уникальный идентификатор процесса (PID);

• родительский процесс (с соответствующим идентификатором, PPID);

• идентификаторы прав доступа (UID, GID, набор групп и т.д.);

• отдельное от всех других процессов адресное пространство;

• программа, работающая в этом адресном пространстве;

• текущий рабочий каталог ('');

• текущий корневой каталог (; его изменение является продвинутой темой);

• набор открытых файлов, каталогов, или и того, и другого;

• маска запретов доступа, использующаяся при создании новых файлов;

• набор строк, представляющих окружение[16];

• приоритеты распределения времени процессора (продвинутая тема);

• установки для размещения сигналов (signal disposition) (продвинутая тема); управляющий терминал (тоже продвинутая тема).

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

Новые процессы всегда создаются существующими процессами. Существующий процесс называется родительским, а новый процесс – порожденным. При загрузке ядро вручную создает первый, изначальный процесс, который запускает программу; идентификатор этого процесса равен 1, он осуществляет несколько административных функций. Все остальные процессы являются потомками. (Родительским процессом является ядро, часто обозначаемое в списках как процесс с ID 0.)

Отношение порожденный‑родительский является отношением один к одному; у каждого процесса есть только один родитель, поэтому легко выяснить PID родителя. Отношение родительский‑порожденный является отношением один ко многим; каждый данный процесс может создать потенциально неограниченное число порожденных. Поэтому для процесса нет простого способа выяснить все PID своих потомков. (Во всяком случае, на практике это не требуется.) Родительский процесс можно настроить так, чтобы он получал уведомление при завершении порожденного процесса, он может также явным образом ожидать наступления такого события.

Адресное пространство (память) каждого процесса отделена от адресного пространства всех остальных процессов. Если два процесса не договорились явным образом разделять память, один процесс не может повлиять на адресное пространство другого. Это важно; это обеспечивает базовый уровень безопасности и надежности системы. (В целях эффективности, система разделяет исполняемый код одной программы с правом доступа только для чтения между всеми процессами, запустившими эту программу. Это прозрачно для пользователя и запущенной программы.)

Текущий рабочий каталог – это каталог, относительно которого отсчитываются относительные пути файлов (те, которые не начинаются с ''). Это каталог, в котором вы находитесь, когда набираете команду оболочки ' someplace '.

По соглашению, все программы запускаются с тремя уже открытыми файлами: стандартным вводом, стандартным выводом и стандартной ошибкой. Это места, откуда принимается ввод, куда направляется вывод и куда направляются сообщения об ошибках соответственно. На протяжении этой книги мы увидим, как они назначаются. Родительский процесс может открыть дополнительные файлы и сделать их доступными для порожденных процессов; порожденный процесс должен каким‑то образом узнать, что они есть, либо посредством какого‑либо соглашения, либо через аргументы командной строки или переменную окружения.

Окружение представляет собой набор строк, каждая в виде ''. Для запроса и установки значений переменных окружения имеются специальные функции, а порожденные процессы наследуют окружение своих родителей. Типичными переменными окружения оболочки являются PATH и НОМЕ. Многие программы для управления своим поведением полагаются на наличие и значения определенных переменных окружения.

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

 

Каналы: сцепление процессов

 

Без сомнения, вам приходилось использовать конструкцию ('') оболочки для соединения двух или более запущенных программ. Канал действует подобно файлу: один процесс записывает в него, используя обычную операцию записи, а другой процесс считывает из него с помощью операции чтения. Процессы (обычно) не знают, что их ввод/вывод является каналом, а не обычным файлом.

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

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

 

 


Поделиться с друзьями:

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

Индивидуальные очистные сооружения: К классу индивидуальных очистных сооружений относят сооружения, пропускная способность которых...

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.058 с.