Текст книги "Операционная система UNIX"
Автор книги: Андрей Робачевский
Жанр:
ОС и Сети
сообщить о нарушении
Текущая страница: 23 (всего у книги 39 страниц)
Заканчивая разговор о межпроцессном взаимодействии в UNIX, приведем сводную сравнительную таблицу рассмотренных систем.
— | Имя файла | Ключ | Ключ | Имя файла | |
Системный канал | Именованный канал | Очередь сообщений | Разделяемая область памяти | Коммуникационный узел | |
pipe() | mknod() | msgget() | shmget() | socket() | |
pipe() | open() | msgget() | shmat() | bind() connect() | |
read() write() | read() write() | msgrcv() msgsnd() | Непосредственный доступ memcpy() | read() write() recv() send() recvfrom() sendto() | |
close() | close() unlink() | msgctl() | shmdt() | close() unlink() |
Если говорить о производительности IPC, то наиболее быстрым способом передачи данных между неродственными процессами является разделяемая память. Разделяемая память является частью адресного пространства для каждого из взаимодействующих процессов, поэтому чтение и запись в эту область неотличимы, например, от чтения и записи в область собственных данных процесса. Однако при использовании разделяемой памяти необходимо обеспечить синхронизацию процессов. При использовании семафоров, необходимо иметь в виду следующие обстоятельства:
□ Применение семафоров может увеличить число процессов в очереди на выполнение, поскольку несколько процессов, ожидающих разрешающего сигнала семафора, будут одновременно разбужены и переведены в очередь на выполнение.
□ Применение семафоров увеличивает число переключений контекста, что, в свою очередь, увеличивает нагрузку на систему.
□ В то же время, использование семафоров является наиболее стандартным (POSIX.1b), хотя и неэффективным способом обеспечения синхронизации.
Очереди сообщений предназначены для обмена короткими (обычно менее 1 Кбайт) структурами данных. Если объем данных превышает эту величину, использование сообщений может значительно увеличить число системных вызовов и уменьшить производительность операционной системы.
Интенсивность межпроцессного взаимодействия в системе можно определить с помощью команды sar -m. Вывод команды показывает число использования объектов IPC в секунду:
17:47:53 msg/s sema/s
17:47:58 0.20 20.00
17:48:03 0.60 12.20
17:48:08 2.20 10.40
17:48:13 0.80 25.10
17:48:18 0.00 15.60
Average 0.76 16.66
Заключение
В этой главе начато обсуждение внутренней архитектуры ядра UNIX, которое будет продолжено в следующих главах. Поскольку процессы являются движущей силой операционной системы, мы начали обсуждение именно с этого вопроса. Действительно, не считая нескольких системных процессов, являющихся частью ядра и выполняющих узкосистемные функции, основная работа операционной системы происходит по запросам и в контексте прикладных процессов.
В главе обсуждается, каким образом прикладной процесс взаимодействует с ядром операционной системы, как происходит справедливое распределение системных ресурсов между задачами, и тем самым обеспечивается многозадачность UNIX. Также рассматриваются принципы организации виртуальной памяти, когда каждый процесс имеет независимое адресное пространство, размер которого в ряде случаев значительно превышает объем оперативной памяти компьютера. Наконец, здесь представлены структуры данных ядра, связанные с управлением процессами и памятью.
Глава 4
Файловая подсистема
Большинство данных в операционной системе UNIX хранится в файлах, организованных в виде дерева и расположенных на некотором носителе данных. Обычно это локальный (т. е. расположенный на том же компьютере, что и сама операционная система) жесткий диск, хотя специальный тип файловой системы – NFS (Network File System) обеспечивает хранение файлов на удаленном компьютере. Файловая система также может располагаться на CD-ROM, дискетах и других типах носителей, однако для простоты изложения сначала мы рассмотрим традиционную файловую систему UNIX, расположенную на обычном жестком диске компьютера.
Исконной файловой системой UNIX System V является s5fs. Файловая система, разработанная в Беркли, FFS, появилась позже, в версии 4.2 BSD UNIX. По сравнению с s5fs она обладает лучшей производительностью, функциональностью и надежностью. Файловые системы современных версий UNIX имеют весьма сложную архитектуру, различную для разных версий. Несмотря на это все они используют базовые идеи, заложенные разработчиками UNIX в AT&T и Калифорнийском университете в Беркли. Поэтому мы проиллюстрируем основные принципы организации файловой системы UNIX на примере базовых систем System V (s5fs) и BSD (FFS), которые, кстати, и сегодня поддерживаются в большинстве версий UNIX.
Когда появилась файловая система FFS, архитектура UNIX поддерживала работу только с одним типом файловой системы. Таким образом, создатели различных версий операционной системы UNIX вынуждены были выбирать одну файловую систему из нескольких возможных. Это неудобство было преодолено введением независимой или виртуальной файловой системы – архитектуры, позволяющей обеспечивать работу с несколькими «физическими» файловыми системами различных типов. В этой главе мы рассмотрим реализацию виртуальной файловой системы, разработанную фирмой Sun Microsystems. Данная архитектура является стандартом для SVR4, однако и другие версии UNIX используют подобные подходы. В качестве примера можно привести независимую файловую систему SCO UNIX.
Далее мы рассмотрим схему доступа прикладных процессов к файлам – всю цепочку структур данных от файловых дескрипторов процесса до фактических дисковых данных, которую операционная система создает в результате открытия процессом файла и которая затем используется для обмена данными.
В заключение мы рассмотрим буферный кэш – подсистему, которая позволяет значительно увеличить производительность работы с дисковыми данными.
Базовая файловая система System V
Каждый жесткий диск состоит из одной или нескольких логических частей, называемых разделами (partitions). Расположение и размер раздела определяются при форматировании диска. В UNIX разделы выступают в качестве независимых устройств, доступ к которым осуществляется как к различным носителям данных.
Например, диск может состоять из четырех разделов, каждый из которых содержит свою файловую систему. Заметим, что в разделе может располагаться только одна файловая система, которая не может занимать несколько разделов. В другой конфигурации диск может состоять только из одного раздела, позволяя создание весьма емких файловых систем.
Файловая система s5fs занимает раздел диска и состоит из трех основных компонентов, как показано на рис. 4.1.
Рис. 4.1. Структура файловой системы s5fs
□ Суперблок (superblocк). Содержит общую информацию о файловой системе, например, об ее архитектуре, общем числе блоков и индексных дескрипторов, или метаданных (inode).
□ Массив индексных дескрипторов (ilist). Содержит метаданные всех файлов файловой системы. Индексный дескриптор содержит статусную информацию о файле и указывает на расположение данных этого файла. Ядро обращается к inode по индексу в массиве ilist. Один inode является корневым (root) inode файловой системы, через него обеспечивается доступ к структуре каталогов и файлов после монтирования файловой системы. Размер массива ilist является фиксированным и задается при создании файловой системы. Таким образом, файловая система s5fs имеет ограничение по числу файлов, которые могут храниться в ней, независимо от размера этих файлов.
□ Блоки хранения данных. Данные обычных файлов и каталогов хранятся в блоках. Обработка файла осуществляется через inode, содержащего ссылки на блоки данных. Блоки хранения данных занимают большую часть дискового раздела, и их число определяет максимальный суммарный объем файлов данной файловой системы. Размер блока кратен 512 байтам, например файловая система S51K SCO UNIX использует размер блока в 1 Кбайт (отсюда и название).
Рассмотрим подробнее каждый из перечисленных компонентов.
СуперблокСуперблок содержит информацию, необходимую для монтирования и управления работой файловой системы в целом (например, для размещения новых файлов). В каждой файловой системе существует только один суперблок, который располагается в начале раздела. Суперблок считывается в память при монтировании файловой системы и находится там до ее отключения (размонтирования).
Суперблок содержит следующую информацию:
□ Тип файловой системы (s_type
)
□ Размер файловой системы в логических блоках, включая сам суперблок, ilist и блоки хранения данных (s_fsize
)
□ Размер массива индексных дескрипторов (s_isize
)
□ Число свободных блоков, доступных для размещения (s_tfree
)
□ Число свободных inode, доступных для размещения (s_tinode
)
□ Флаги (флаг модификации s_fmod
, флаг режима монтирования s_fronly
)
□ Размер логического блока (512, 1024, 2048)
□ Список номеров свободных inode
□ Список адресов свободных блоков
Поскольку число свободных inode и блоков хранения данных может быть значительным, хранение двух последних списков целиком в суперблоке непрактично. Например, для индексных дескрипторов хранится только часть списка. Когда число свободных inode в этом списке приближается к 0, ядро просматривает ilist и вновь формирует список свободных inode. Для этого ядро анализирует поле di_mode
индексного дескриптора, которое равно 0 у свободных inode.
К сожалению, такой подход неприменим в отношении свободных блоков хранения данных, поскольку по содержимому блока нельзя определить, свободен он или нет. Поэтому необходимо хранить список адресов свободных блоков целиком. Список адресов свободных блоков может занимать несколько блоков хранения данных, но суперблок содержит только один блок этого списка. Первый элемент этого блока указывает на блок, хранящий продолжение списка и т.д., как это показано на рис. 4.1.
Выделение свободных блоков для размещения файла производится с конца списка суперблока. Когда в списке остается единственный элемент, ядро интерпретирует его как указатель на блок, содержащий продолжение списка. В этом случае содержимое этого блока считывается в суперблок и блок становится свободным. Такой подход позволяет использовать дисковое пространство под списки, пропорциональное свободному месту в файловой системе. Другими словами, когда свободного места практически не остается, список адресов свободных блоков целиком помещается в суперблоке.
Индексные дескрипторыИндексный дескриптор, или inode, содержит информацию о файле, необходимую для обработки данных, т.е. метаданные файла. Каждый файл ассоциирован с одним inode, хотя может иметь несколько имен в файловой системе, каждое из которых указывает на один и тот же inode.
Индексный дескриптор не содержит:
□ имени файла, которое содержится в блоках хранения данных каталога;
□ содержимого файла, которое размещено в блоках хранения данных.
При открытии файла ядро помещает копию дискового inode в память в таблицу in-core inode, которая содержит несколько дополнительных полей. Структура дискового inode (struct dinode
) приведена на рис. 4.2. Основные поля дискового inode следующие:
di_mode | Тип файла, дополнительные атрибуты выполнения и права доступа. |
di_nlinks | Число ссылок на файл, т.е. количество имен, которые имеет файл в файловой системе. |
di_uid , di_gid | Идентификаторы владельца-пользователя и владельца– группы. |
di_size | Размер файла в байтах. Для специальных файлов это поле содержит старший и младший номера устройства. |
di_atime | Время последнего доступа к файлу. |
di_mtime | Время последней модификации. |
di_ctime | Время последней модификации inode (кроме модификации полей di_atime, di_mtime). |
di_addr[13] | Массив адресов дисковых блоков хранения данных. |
Рис. 4.2. Структура дискового inode
Поле di_mode
хранит несколько атрибутов файла: тип файла (IFREG
для обычных файлов, IFDIR
для каталогов, IFBLK
или IFCHR
для специальных файлов блочных и символьных устройств соответственно); права доступа к файлу для трех классов пользователей и дополнительные атрибуты выполнения (SUID, SGID и sticky bit), значения этих атрибутов были подробно рассмотрены в главе 1.
Заметим, что в индексном дескрипторе отсутствует информация о времени создания файла. Вместо этого inode хранит три значения времени: время последнего доступа (di_atime
), время последней модификации содержимого файла (di_mtime
) и время последней модификации метаданных файла (di_ctime
). В последнем случае не учитываются модификации полей di_atime
и di_mtime
. Таким образом, di_ctime
изменяется, когда изменяется размер файла, владелец, группа, или число связей.
Индексный дескриптор содержит информацию о расположении данных файла. Поскольку дисковые блоки хранения данных файла в общем случае располагаются не последовательно, inode должен хранить физические адреса всех блоков, принадлежащих данному файлу.[46]46
Размещение данных файла в произвольно расположенных дисковых блоках позволяет эффективно использовать дисковое пространство, поскольку ядро может использовать любой свободный дисковый блок для размещения данных. Однако в файловой системе s5fs блок может использоваться только одним файлом, поэтому последний блок файла используется, как правило, не полностью. К тому же такой подход с течением времени приводит к увеличению фрагментации системы, когда данные файла оказываются произвольно разбросанными по диску, что, в свою очередь, увеличивает время доступа к файлу и уменьшает производительность обмена данными. Единственным способом уменьшения фрагментации файловой системы является создание полной резервной копии на другом носителе (или в другой файловой системе) и затем её восстановлении. При этом запись файлов будет производиться последовательно без фрагментации.
[Закрыть] В индексном дескрипторе эта информация хранится в виде массива, каждый элемент которого содержит физический адрес дискового блока, а индексом массива является номер логического блока файла. Массив имеет фиксированный размер и состоит из 13 элементов. При этом первые 10 элементов адресуют непосредственно блоки хранения данных файла. Одиннадцатый элемент адресует блок, в свою очередь содержащий адреса блоков хранения данных. Двенадцатый элемент указывает на дисковый блок, также хранящий адреса блоков, каждый из который адресует блок хранения данных файла. И, наконец, тринадцатый элемент используется для тройной косвенной адресации, когда для нахождения адреса блока хранения данных файла используются три дополнительных блока.
Такой подход позволяет при относительно небольшом фиксированном размере индексного дескриптора поддерживать работу с файлами, размер которых может изменяться от нескольких байтов до десятка мегабайтов. Для относительно небольших файлов (до 10 Кбайт при размере блока 1024 байтов) используется прямая индексация, обеспечивающая максимальную производительность. Для файлов, размер которых не превышает 266 Кбайт (10 Кбайт + 256×1024), достаточно простой косвенной адресации. Наконец, при использовании тройной косвенной адресации можно обеспечить доступ к 16777216 блокам (256×256×256).
Файлы в UNIX могут содержать так называемые дыры. Например, процесс может создать пустой файл, с помощью системного вызова lseek(2) сместить файловый указатель относительно начала файла и записать данные. При этом между началом файла и началом записанных данных образуется дыра – незаполненная область. При чтении этой области процесс получит обнуленные байты. Поскольку логические блоки, соответствующие дыре, не содержат данные, не имеет смысла размещать для них дисковые блоки. В этом случае соответствующие элементы массива адресов inode содержат нулевой указатель. Когда процесс производит чтение такого блока, ядро возвращает последовательность нулей. Дисковые блоки размещаются только при записи в соответствующие логические блоки файла.[47]47
Отсутствие размещенных дисковых блоков для части файла может привести к нежелательным результатам. Например, операция записи в «дыру» может закончиться неудачей из-за нехватки дискового пространства. При копировании файла с дырой, его копия будет занимать больше фактического места на диске, чем оригинал. Это связано с тем, что при копировании производится чтение содержимого оригинала, а затем – запись в другой файл. Это, в частности может привести к тому, что резервная копия файловой системы не сможет быть обратно распакована, поскольку вместо неразмещенных блоков будет хранить законные нулевые байты и, соответственно, занимать больше места.
[Закрыть]
Как мы уже видели, ни метаданные, ни тем более блоки хранения данных, не содержат имени файла. Имя файла хранится в файлах специального типа – каталогах. Такой подход позволяет любому файлу, т. е. фактическим данным, иметь теоретически неограниченное число имен (названий), в файловой системе. При этом несколько имен файлов будут соответствовать одним и тем же метаданным и данным и являться жесткими связями.
Каталог файловой системы s5fs представляет собой таблицу, каждый элемент которой имеет фиксированный размер в 16 байтов: 2 байта хранят номер индексного дескриптора файла, а 14 байтов – его имя. Это накладывает ограничение на число inode, которое не может превышать 65 535. Также ограничена и длина имени файла: его максимальный размер – 14 символов. Структура каталога приведена на рис. 4.3.
Рис. 4.3. Каталог файловой системы s5fs
Первые два элемента каталога адресуют сам каталог (текущий каталог) под именем "." и родительский каталог под именем "..".
При удалении имени файла из каталога (например, с помощью команды rm(1)), номер inode соответствующего элемента устанавливается равным 0. Ядро обычно не удаляет такие свободные элементы, поэтому размер каталога не уменьшается даже при удалении файлов. Это является потенциальной проблемой для каталогов, в которые временно было помещено большое количество файлов. После удаления большинства из них размер каталога останется достаточно большим, поскольку записи удаленных файлов будут по-прежнему существовать.
Иллюстрацию этого явления в SCO UNIX можно привести, применив команду hd(1M), обеспечивающую вывод неинтерпретированного содержимого файла (шестнадцатеричный дамп).
$ hd .
0000 fc 0a 2e 00 00 00 00 00 00 00 00 00 00 00 00 00
0010 02 00 2е 2е 00 00 00 00 00 00 00 00 00 00 00 00
0020 33 72 6d 61 69 6с 00 00 00 00 00 00 00 00 00 00 3rmail
0030 0а 2с 4е 65 77 73 00 00 00 00 00 00 00 00 00 00 .,News
0040 33 7d 2е 6e 65 77 73 72 63 00 00 00 00 00 00 00 3}.newsrc
0050 00 40 62 69 6e 00 00 00 00 00 00 00 00 00 00 00 .@bin
0060 da 91 64 65 61 64 2е 6с 65 74 74 65 72 00 00 00 ..dead.letter...
0290 00 00 70 69 6e 65 72 63 30 30 30 37 36 39 00 00 ..pinerc000769..
02a0 00 00 30 35 6e 61 64 75 76 61 2е 6а 70 67 00 00 ..05naduva.jpg..
02b0 00 00 30 36 73 70 75 73 74 69 2е 6а 70 67 00 00 ..06spusti.jpg..
02с0 00 00 30 37 67 75 69 74 61 72 2е 6а 70 67 00 00 ..07guitar.jpg..
02d0 00 00 30 38 73 75 6e 73 65 74 2е 6а 70 67 00 00 ..08sunset.jpg..
02е0 00 00 37 31 72 6f 70 65 73 31 2е 6а 70 67 00 00 ..71ropes1.jpg..
Можно заметить, что имен файлов, расположенных во второй части вывода команды hd(1M) на самом деле не существует – об этом свидетельствуют нулевые значения номеров inode, это же подтверждает вывод команды ls(1):
$ ls -а
.newsrc
bin
dead.letter
News
mail
Файловая систем s5fs привлекательна благодаря своей простоте. Однако обратной стороной медали является низкая надежность и производительность.
С точки зрения надежности слабым местом этой файловой системы является суперблок. Суперблок несет основную информацию о файловой системе в целом, и при его повреждении файловая система не может использоваться. Поскольку в файловой системе s5fs суперблок хранится в единственном варианте, вероятность возникновения ошибок достаточно велика.
Относительно низкая производительность связана с размещением компонентов файловой системы на диске. Метаданные файлов располагаются в начале файловой системы, а далее следуют блоки хранения данных. При работе с файлом, происходит обращение как к его метаданным, так и к дисковым блокам, содержащим его данные. Поскольку эти структуры данных могут быть значительно разнесены в дисковом пространстве, необходимость постоянного перемещения головки диска увеличивает время доступа и, как следствие, уменьшает производительность файловой системы в целом. К этому же эффекту приводит фрагментация файловой системы, поскольку отдельные блоки файла оказываются разбросанными по всему разделу диска.
Использование дискового пространства также не оптимально. Для увеличения производительности файловой системы более предпочтительным является использование блоков больших размеров. Это позволяет считывать большее количество данных за одну операцию ввода/вывода. Так, например, в UNIX SVR2 размер блока составлял 512 байтов, а в SVR3 – уже 1024 байтов. Однако поскольку блок может использоваться только одним файлом, увеличение размера блока приводит к увеличению неиспользуемого дискового пространства за счет частичного заполнения последнего блока файла. В среднем для каждого файла теряется половина блока.
Массив inode имеет фиксированный размер, задаваемый при создании файловой системы. Этот размер накладывает ограничение на максимальное число файлов, которые могут существовать в файловой системе. Расположение границы между метаданными файлов и их данными (блоками хранения данных) может оказаться неоптимальным, приводящим либо к нехватке inode, если файловая система хранит файлы небольшого размера, либо к нехватке дисковых блоков для хранения файлов большого размера. Поскольку динамически изменить эту границу невозможно, всегда останется неиспользованное дисковое пространство либо в массиве inode, либо в блоках хранения данных.
Наконец, ограничения, накладываемые на длину имени файла (14 символов) и общее максимальное число inode (65 535), также являются слишком жесткими.
Все эти недостатки привели к разработке новой архитектуры файловой системы, которая появилась в версии 4.2BSD UNIX под названием Berkeley Fast File System, или FSS.