Материалы для самоподготовки к вопросам по ОС из программы

advertisement
Оглавление
Теоретические вопросы ................................................................................................................2
Межпроцессное взаимодействие, критерий отсутствия состязательности, классические
реализации концепции критических областей на примере семафоров и мьютексов. ........2
Взаимоблокировка, условия Коффмана, критерий возникновения взаимоблокировки на
графе Холта ................................................................................................................................4
Файловая система. Структура тома NTFS, файловые потоки, принципы хранения
резидентных и нерезидентных файлов. ...................................................................................6
Практические вопросы ..................................................................................................................9
Запрограммируйте псевдокодом (синтаксически основанным на паскале или си)
решение проблемы производителя и потребителя. ................................................................9
Для ОС Linux задайте режим доступа к файлу, позволяющий владельцу файла чтение,
запись и исполнение, группе — только чтение, прочим пользователям — ничего.
Постройте соответствующий 8-чный код. Объясните, будет работать такой режим
доступа, если установить его для каталога. ..........................................................................12
Для файла имеющего структуру, изображенную на рисунке, постройте регулярное
выражение, фильтрующее строки, в которых имя сотрудника начинается на букву "R".
...................................................................................................................................................16
1
Теоретические вопросы
Межпроцессное взаимодействие, критерий отсутствия состязательности,
классические реализации концепции критических областей на примере семафоров
и мьютексов.
Процессам (и потокам) необходимо взаимодействовать друг с другом. При этом
возникает ряд ситуаций, требующих дополнительного регулирования. Например, если
несколько процессов используют один и тот же ресурс, необходимо контролировать
последовательность получения доступа, чтобы процессы работали корректно.
Рассмотрим способы организации межпроцессорных взаимодействий.
Пример. Спулер (spooler)
Пусть процессу необходимо вывести страницу (или несколько страниц) на печать,
он помещает данные для печати в спулер (в зависимости от операционной
системы это может быть каталог, файл или область памяти). Другой процесс,
отвечающий за печать, по очереди берёт переданные задания и выводит их на
принтер.
Тем самым снимается конкуренция за использование принтера различными
процессами. Кроме того, процесс печати может решать по каким-либо
определённым правилам в какой очерёдности следует пускать задания на печать.
Заметим, что спулер в данном примере реализует межпроцессное
взаимодействие, в котором множество процессов желающих вывести данные на
принтер взаимодействуют через общий ресурс (спулер) с печатающим процессом.
При этом ресурс "принтер" по сути монопольно занят один единственным
печатающим процессом.
В случае взаимодействия двух произвольных процессов, не всегда возможно
организовать в операционной системе специальный процесс для регулирования этих
взаимодействий. Чтобы решить задачи взаимодействий на совместно используемых
ресурсах вводят некоторые специальные понятия.
Критическая секция (или критическая область) — это часть программы, в которой
происходит обращение к совместно используемым ресурсам.
Критерий отсутствия состязательности. Два и более процессов, использующих
один и тот же общий ресурс не состязаются за этот ресурс тогда и только когда, когда в
критической секции, связанной с этим ресурсом одновременно находится не более чем
один из этих процессов.
В самом деле, часть времени процесс занимается внутренними расчётами и не
использует общий ресурс. Как только этот процесс входит в критическую секцию, т.е.
происходит работа с общим ресурсом, об этом особым образом становится известно. Если
в это время (пока первый процесс не вышел из критической секции) какой-либо другой
процесс попробует войти в критическую секцию (т.е. начать работать с общим ресурсом),
ему будет в этом отказано. Точнее, второй процесс будет приостановлен до тех пор, пока
первый не выйдет из критической секции. Это можно проиллюстрировать на рисунке.
2
Процессы
1
2
Выполнение
Критическая
секция
Выполнение
Блокирован
Выполнение
Критическая
секция
Время
Рисунок 1. Исключение состязательности с использованием критических областей
Теоретическая концепция критических областей имеет несколько стандартных
реализаций, применяемых в различных операционных системах. Подробно рассмотрим
лишь некоторые из них.
1. Запрет прерываний.
Если прерывания запрещены, то невозможно и переключение на другой
процесс, который может состязаться за какие-либо ресурсы. Однако такой
подход весьма неразумен, поскольку заранее не известно время, которое
процесс будет находиться в критической области. Таким образом, пока
пользовательский процесс в критической секции, не сможет произойти ни одна
обработка, в том числе системных и неотложных событий.
2. Переменные блокировки
Если процессы используют один и тот же ресурс, разумно использовать
некоторую общую переменную — переменную блокировки — которую
изначально положить равной 0, а когда процесс будет входить в критическую
область, он будет менять значение этой переменной на 1. Таким образом, если
некоторый процесс хочет войти в критическую секцию, а переменная
блокировки равна 1, процесс будет ожидать до тех пор, пока переменная
блокировки не обратится в 0, что будет означать в критической секции не
находится ни одного процесса.
Кроме рассмотренных можно назвать распространённые реализации: строгое
чередование, алгоритм Петерсона, установка блокировки процессора (TLS, Test and Set
Lock).
3
Взаимоблокировка, условия Коффмана, критерий возникновения взаимоблокировки
на графе Холта
В компьютерных системах существует большое количество ресурсов, каждый из
которых в конкретный момент времени может использоваться только одним процессом.
В качестве таких примеров можно привести принтеры, накопители на магнитной ленте и
элементы внутренних таблиц системы. Появление двух процессов, одновременно
передающих данные на принтер, приведет к печати бессмысленного набора символов.
Наличие двух процессов, использующих один и тот же элемент таблицы файловой
системы, обязательно станет причиной разрушения файловой системы. Поэтому все
операционные системы обладают способностью предоставлять процессу эксклюзивный
доступ (по крайней мере, временный) к определенным ресурсам.
Часто для выполнения прикладных задач процесс нуждается в исключительном
доступе не к одному, а к нескольким ресурсам.
Пример. Взаимоблокировка
Предположим, что каждый из двух процессов хочет записать отсканированный
документ на компакт-диск. Процесс A запрашивает разрешение на использование
сканера и получает его. Процесс B запрограммирован по-другому, поэтому
сначала запрашивает устройство для записи компакт-дисков и также получает его.
Затем процесс A обращается к устройству для записи компакт-дисков, но запрос
отклоняется до тех пор, пока это устройство занято процессом B. К сожалению,
вместо того чтобы освободить устройство для записи компакт-дисков, B
запрашивает сканер. В этот момент процессы заблокированы и будут вечно
оставаться в этом состоянии. Такая ситуация называется тупиком, тупиковой
ситуацией или взаимоблокировкой.
В сложно организованной системе с большим количеством ресурсов и
одновременно исполняемых процессов взаимоблокировка весьма вероятна. При этом
под ресурсами (понятие ресурса было введено в первом параграфе) можно понимать, в
том числе, и сами процессы. Обобщая, ресурсом можно назвать любой объект, к
которому может получить доступ процесс.
Ресурсы можно разбить на два класса:
1. Выгружаемым назовём такой ресурс, который можно безболезненно забирать у
владеющего им процесса. К такому ресурсу можно отнести, например, память.
Пока процесс приостановлен, можно безболезненно выгрузить содержимое
памяти на диск, при этом отдав освободившийся объём памяти другому процессу.
Когда настанет момент восстановить процесс, память которого была выгружена,
выгруженные данные с диска прочитываются и помещаются в память, после чего
процесс запускается вновь.
2. Невыгружаемым назовём такой ресурс, который нельзя забрать у процесса, не
потеряв результатов работы этого процесса. К примеру, если в момент записи
отнять у процесса записывающее устройство и передать его в пользование другому
процессу, все данные первого процесса будут потеряны безвозвратно.
4
Справедливости ради заметим, что взаимная блокировка может возникнуть лишь
на втором классе ресурсов, поскольку если в тупиковой ситуации задействованы ресурсы
первого класса, ситуацию можно разрешить, принудительно выгрузив ресурс,
позаботившись при этом о его дальнейшем восстановлении.
Взаимоблокировка — это тупиковая ситуация, характеризующаяся тем, что группа
процессов ожидает события, которое может вызвать только другой процесс из этой
же группы.
Так как все процессы находятся в состоянии ожидания, ни один из них не будет
причиной какого-либо события, которое могло бы активировать любой другой процесс в
группе, и все процессы продолжают ждать до бесконечности. В этой модели мы
предполагаем, что процессы имеют только один поток и что нет прерываний, способных
активизировать заблокированный процесс. Условие отсутствия прерываний необходимо,
чтобы предотвратить ситуацию, когда тот или иной заблокированный процесс
активизируется, скажем, по сигналу тревоги и затем приводит к событию, которое
освободит другие процессы в группе.
В большинстве случаев событием, которого ждет каждый процесс, является
освобождение какого-либо ресурса, в данный момент занятого другим участником
группы. Другими словами, каждый участник в группе процессов, зашедших в тупик, ждет
доступа к ресурсу, принадлежащему заблокированному процессу. Ни один из процессов
не может работать, ни один из них не может освободить какой-либо ресурс и ни один из
них не может возобновиться. Количество процессов и количество и вид ресурсов,
имеющихся и запрашиваемых, здесь не важны. Результат остается тем же самым для
любого вида ресурсов, аппаратных и программных.
Необходимые условия возникновения взаимоблокировки — условия Коффмана
(Coffman):
1. Условие взаимного исключения. Каждый ресурс в данный момент или отдан ровно
одному процессу, или доступен.
2. Условие удержания и ожидания. Процессы, в данный момент удерживающие
полученные ранее ресурсы, могут запрашивать новые ресурсы.
3. Условие отсутствия принудительной выгрузки ресурса. У процесса нельзя
принудительным образом забрать ранее полученные ресурсы. Процесс, владеющий ими, должен сам освободить ресурсы.
4. Условие
циклического
ожидания.
Должна
существовать
круговая
последовательность из двух и более процессов, каждый из которых ждет доступа к
ресурсу, удерживаемому следующим членом последовательности.
Указанные условия являются необходимыми. То есть, если хоть одно из них не
выполняется, то взаимоблокировка никогда не возникнет. Достаточность не имеет места
быть: если выполняются все четыре условия, взаимоблокировка может и не произойти,
например, если в системе нет процессов, претендующих на одновременное
использование одних и тех же ресурсов.
Следует отметить, что каждое условие относится к правилам, установленным в
данной конкретной операционной системе. К сожалению, практически невозможно
5
спроектировать операционную систему так, чтобы полностью исключить хоть одно из
условий
Коффмана
заранее.
Однако
существуют
варианты
разрушения
взаимоблокировок, основанные на принудительном исключении какого-либо из этих
условий.
Отслеживать возникновение взаимоблокировок удобно на диаграммах Холта
(Holt). Диаграмма Холта представляет собой направленный граф1, имеющий два типа
узлов: процессы (показываются кружочками) и ресурсы (показываются квадратиками). Тот
факт, что ресурс получен процессом и в данный момент занят этим процессом,
указывается ребром (стрелкой) от ресурса к процессу. Ребро, направленное от процесса, к
ресурсу, означает, что процесс в данный момент блокирован и находится в состоянии
ожидания доступа к соответствующему ресурсу.
Процесс B
Сканер
Устройство
записи
компактдисков
Процесс А
Рисунок 2. Диаграмма Холта для примера 3.5 взаимоблокировки
Критерий взаимоблокировки. Взаимоблокировка имеет место быть, тогда и только тогда,
когда диаграмма Холта, отражающая состояния процессов и ресурсов, содержит цикл2.
Файловая система. Структура тома NTFS, файловые потоки, принципы хранения
резидентных и нерезидентных файлов.
Каждый том (т.е. дисковый раздел) NTFS представляет собой линейную
последовательность блоков (кластеров). Размер блока фиксирован для каждого тома и
варьируется от 512 байт (1 сектор) до 64 Кбайт. В большинстве случаев используется
размер в 4 Кбайта.
Главной структурой данных в каждом томе является главная файловая таблица
MFT (Master File Table), представляющая собой линейную последовательность записей
фиксированного (1 Кбайт) размера. Каждая запись MFT описывает один файл или один
1
Граф — это пара
, где
— это множество вершин
, а
— множество рёбер
. Граф называется ориентированным или направленным,
если
. Ребра направленного графа на диаграмме обозначаются стрелками.
2
Говорят что граф содержит цикл, если начиная с некоторой вершины, переходя по рёбрам, можно какимлибо образом вернуться в эту же самую вершину.
6
каталог. В ней содержатся атрибуты файла, такие как его имя и временные штампы, а
также список дисковых адресов, указывающих на расположение блоков файла. Если файл
очень большой и необходимо использовать две и более записей главной таблицы для
перечисления всех блоков, первая запись MFT, посвященная данному файлу, указывает на
другие записи MFT.
Сама главная таблица представляет собой файл и NTFS отводит под него
специальную зону — первые 12% диска. Запись каких-либо данных в эту область
невозможна. MFT-зона всегда держится пустой - это делается для того, чтобы файл с MFT
не фрагментировался при своем росте. Остальные 88% диска представляют собой
обычное пространство для хранения файлов.
Свободное место диска, однако, включает в себя всё физически свободное
место - незаполненные куски MFT-зоны туда тоже включаются. Механизм
использования MFT-зоны таков: когда файлы уже нельзя записывать в
обычное пространство, MFT-зона просто сокращается (в текущих версиях
операционных систем ровно в два раза), освобождая таким образом место
для записи файлов. При освобождении места в обычной области MFT зона
может снова расширится. При этом не исключена ситуация, когда в этой
зоне остались и обычные файлы: никакой аномалии тут нет. Что ж,
система старалась оставить её свободной, но ничего не получилось.
Жизнь продолжается... Метафайл MFT все-таки может фрагментироваться,
хоть это и было бы нежелательно.
Первые 16 записей MFT посвящены описанию специальных служебных файлов,
называемых метафайлами. Каждый из них отвечает за какой-либо аспект работы системы.
Имена метафайлов начинаются с символа $. Они располагаются в корневом каталоге
диска, хотя операционная система тщательно скрывает их присутствие.
Информацию об этих файлах можно получить, изучая MFT. Для них указан
вполне
реальный
размер
—
и
можно
узнать,
например,
сколько
операционная система тратит на каталогизацию всего жесткого диска.
В следующей таблице приведены используемые в данный момент метафайлы и
их назначение.
7
0. $MFT
сам MFT
1. $MFTmirr
копия первых 16 записей MFT, размещенная посередине
диска
2. $LogFile
файл поддержки журналирования (см. ниже)
3. $Volume
служебная информация - метка тома, версия файловой
системы, т.д.
4. $AttrDef
список стандартных атрибутов файлов на томе
5. $.
корневой каталог
6. $Bitmap
карта свободного места тома
7. $Boot
загрузочный сектор (если раздел загрузочный)
11. $Quota
файл, в котором записаны права пользователей на
использование дискового пространства (начал работать
лишь в NT5)
10. $Upcase
файл - таблица соответствия заглавных и прописных букв
в имен файлов на текущем томе. Нужен в основном
потому, что в NTFS имена файлов записываются в
Unicode, что составляет 65 тысяч различных символов,
искать большие и малые эквиваленты которых очень
нетривиально.
Первая запись файла MFT позволяет найти сам этот файл (т.е. получить список
блоков (кластеров), которые он занимает). Очевидно, чтобы найти всю остальную
информацию о файловой системе, у ОС должен быть некий способ нахождения первого
блока файла MFT. Этот номер содержится в загрузочном блоке, куда он помещается при
установке системы.
Каждый файл в NTFS представляет собой набор атрибутов. Атрибут состоит из
заголовка и значения. Запись MFT, описывающая файл, содержит заголовки его атрибутов
и указывает на местонахождение значений.
Так, например, имя файла, записанное в кодировке Unicode, является одним из
его атрибутов. Другим атрибутом файла является его содержимое.
Если значение атрибута занимает достаточно мало места, оно помещается
непосредственно в запись MFT (т.е. внутри записи хранятся и заголовок, и тело атрибута).
Такие атрибуты называются резидентными. Если же длина значения слишком велика,
чтобы поместиться в запись MFT, то значение занимает отдельные блоки диска и атрибут
называется нерезидентным. В записи MFT в этом случае хранится информация о
занимаемых атрибутом блоках. Нерезидентные атрибуты часто также называют потоками
файла.
Как правило, файл в NTFS имеет множество коротких атрибутов и один длинный
— содержимое файла, представляющее собой поток данных. Однако у файла может быть
произвольное количество потоков данных, для обращения к которым необходимо
использовать имя потока (указывается через двоеточие после имени файла).
Многие троянские кони и вирусы прячут себя в дополнительных потоках
данных файла. Дополнительные потоки не видны стандартными средствами.
Наблюдаемый размер файла — это всего лишь размер основного потока.
8
Файл может не иметь потоков вообще, если он пуст, либо слишком мал и
его содержимое помещается непосредственно внутри килобайтовой записи
MFT.
Рассмотрим теперь, как в NTFS отслеживается расположение нерезидентных
атрибутов, в частности, данных.
Для увеличения эффективности дисковые блоки файлам назначаются по
возможности в виде серий последовательных блоков (сегментов файла). Блоки в файле
описываются последовательностью записей, каждая из которых описывает
последовательность логически (НЕ ФИЗИЧЕСКИ) непрерывных блоков.
Непрерывный файл описывается всего одной записью. К этой категории
относятся файлы, записываемые за одну операцию от начала до конца.
Файл с одной «дыркой» (например, файл, для которого определены только
блоки с 0 по 49 и с 60 по 79), будет описываться двумя записями. Такой
файл может быть создан, если сначала записать в него первые 50 блоков,
затем переместить указатель в файле на логический блок 60 и записать
еще 20 блоков. Когда из такого файла читается «дырка», все
отсутствующие байты оказываются нулями.
Каждая запись начинается с заголовка, определяющего смещение первого блока
в файле. Затем располагается смещение первого блока, не покрываемого первой
записью.
Для приведенного выше примера у первой записи будет заголовок (0,50),
а сама запись будет содержать дисковые адреса для первых 50 блоков
файла. Вторая запись будет иметь заголовок (60, 80) и содержать
дисковые адреса для следующих 20 блоков файла.
Следом за каждым заголовком располагаются пары, в которых содержатся
дисковые адреса и длины серий блоков. Эти дисковые адреса представляют собой
смещение блока от начала дискового раздела. Длина серии — это количество блоков в
серии. В записи серии может содержаться любое необходимое количество пар.
Имя файла может содержать любые символы, включая полый набор
национальных алфавитов, так как данные представлены в Unicode — 16-битном
представлении, которое дает 65535 разных символов. Максимальная длина имени
файла — 255 символов.
Практические вопросы
Запрограммируйте псевдокодом (синтаксически основанным на паскале или си)
решение проблемы производителя и потребителя.
Проблема производителя и потребителя. Пусть два процесса совместно используют
буфер ограниченного размера. Один из процессов помещает в буфер информацию
(назовём этот процесс производителем), а другой читает информацию из буфера
(назовём этот процесс потребителем). Трудность возникнет в тот момент, когда
производитель заполнит буфер целиком. Решение очевидно, производитель должен
ожидать пока потребитель прочтёт частично или полностью информацию из буфера.
Аналогичная трудность возникнет, когда потребитель обратится к буферу для чтения и
обнаружит, что буфер пуст. В этом случае потребитель должен ждать, пока производитель
не поместит информацию в буфер.
9
Решение кажется достаточно простым, но приводит к состязательному состоянию
двух процессов, даже при использовании критических секций в реализации
производителя и потребителя. Дело в том, что для учёта заполненности буфера
необходимо использовать какую-то общую для производителя и потребителя
переменную. И как раз за эту переменную процессы будут состязаться. Можно ввести
вспомогательный механизм, решающий задачу, например, установить бит активации,
указывающий можно ли получать доступ к счётчику заполненности буфера. Однако
можно смоделировать ситуацию с несколькими процессами, когда это решение не будет
работать. Требуется сформулировать более общий подход.
В 1965г. Дейкстра (E.W. Dijkstra) предложил использовать специальную
переменную целого типа, получившую название — семафор. Семафор связывается с
совместно используемым ресурсом. Каждое обращение к ресурсу абстрактно будем
называть сигналом активизации.
Семафор — это неотрицательная целочисленная переменная, связанная с
совместно используемым ресурсом, которая может быть нулём (в случае
отсутствия сохранённых сигналов активизации) или некоторым положительным
числом, соответствующим количеству отложенных сигналов активизации.
Над семафорами определены две операции:
1. down(sem) — сравнивает значение семафора с нулём, если значение
больше нуля, то уменьшает его на 1 (то есть расходует один из сохраненных
сигналов активизации) и возвращает управление. Если значение семафора
равно нулю, процедура down() не возвращает управление процессу, а
процесс переводится в состояние ожидания.
2. up(sem) — увеличивает значение семафора на 1. При этом если с этим
семафором связаны один или более ожидающих процессов, которые не
могут завершить более раннюю операцию down(), а это означает что
значение семафора равно 0, один из ожидающих процессов будет выбран
системой и ему будет разрешено завершить down().
Мьютекс —это семафор, находящийся в одном из двух возможных состояний: 0 —
блокирован, либо 1 — не блокирован. Если процесс должен войти в критическую
секцию, и мьютекс не заблокирован, процесс входит в критическую секцию, при
этом заблокировав мьютекс. Если мьютекс заблокирован, вызывающий процесс
блокируется до тех пор, пока процесс, работающий в критической области, не
выйдет из неё.
Решение проблемы производителя и потребителя с помощью семафоров
#define N 100;
/* Определяем размер буфера(в ячейки) */
typedef int semaphore;
/* Задаём тип "семафор" как целый */
semaphore mutex = 1;
/* Контроль входа в критическую область */
semaphore empty = N;
/* Число свободных ячеек буфера */
semaphore full = 0;
/* Число занятых ячеек буфера */
void producer(){
void consumer(){
/* Переменная "элемент", в неё
/* Переменная "элемент", в неё
будем класть вновь созданный элемент,
будем класть взятый из буфера для
для дальнейшей отправки в буфер */
обработки элемент */
int item;
int item;
10
/* Бесконечный цикл */
while (TRUE){
/* Создать элемент */
item=produce_item();
/* Уменьшить empty */
down(empty);
/* Войти в критическую
область*/
down(mutex);
/* Поместить в буфер
созданный элемент */
put_item(item);
/* Выход из критической
области */
up(mutex);
/* Увеличить full */
up(full);
}
}
/* Бесконечный цикл */
while (TRUE){
/* Уменьшить full */
down(full);
/* Войти в критическую
область*/
down(mutex);
/* Поместить в буфер
созданный элемент */
item=get_item();
/* Выход из критической
области */
up(mutex);
/* Увеличить empty */
up(empty);
/* Обработка элемента */
consum_item(item);
}
}
В представленном в примере решении используются три семафора: один для
подсчета заполненных сегментов буфера (full), другой для подсчета пустых сегментов
(empty), а третий предназначен для исключения одновременного доступа к буферу производителя и потребителя (mutex). Значение счетчика full исходно равно нулю, счетчик
empty равен числу сегментов в буфере, a mutex равен 1. Рассмотрим действия обоих
процессов пошагово.
Процесс производитель (producer) создаёт новый элемент, чтобы потом
поместить его в буфер. Следующим шагом семафор, указывающий количество свободных
элементов буфера уменьшается. При этом если уменьшить этот семафор нельзя (в случае,
когда он равен нулю), производитель будет ожидать, пока не появится хоть один
свободный элемент. Если же уменьшение прошло удачно, производитель сообщает о
том, что он входит в критическую секцию (вход будет произведён лишь в том случае, если
потребитель не находится в критической секции). Исполняя критическую секцию,
производитель помещает созданный элемент в буфер, после чего сообщает о выходе из
критической секции и увеличивает семафор, отражающий число заполненных элементов
буфера.
Процесс потребитель (consumer) уменьшает значение семафора, указывающее
количество занятых элементов буфера. При этом, если семафор нельзя уменьшить (он
равен нулю), потребитель будет ожидать, пока в буфере не появится хоть один
заполненный элемент. Если уменьшение прошло успешно, потребитель уменьшает
мьютекс, тем самым сообщая о входе в критическую секцию. Вход в критическую секцию
произойдёт только если производитель не находится в критической секции, в противном
случае потребитель будет ожидать, пока производитель не выйдет из критической
секции. Исполняя критическую секцию, потребитель забирает из буфера элемент, после
чего сообщает о выходе из критической секции и увеличивает семафор, отражающий
число свободных элементов буфера. Завершающим этапом, потребитель обрабатывает
полученный из буфера элемент.
В примере семафоры использовались двумя различными способами. Это
различие достаточно значимо, чтобы сказать о нем особо. Семафор mutex используется
для реализации взаимного исключения, то есть для исключения одновременного
обращения к буферу и связанным переменным двух процессов.
11
Для ОС Linux задайте режим доступа к файлу, позволяющий владельцу файла
чтение, запись и исполнение, группе — только чтение, прочим пользователям —
ничего. Постройте соответствующий 8-чный код. Объясните, будет работать такой
режим доступа, если установить его для каталога.
В основе механизмов разграничения доступа в ОС Linux лежат имена
пользователей и имена групп пользователей. В системе создается некоторое число групп
пользователей, причем каждый пользователь может быть включен в одну или несколько
групп. Создает и удаляет группы суперпользователь, он же может изменять состав
участников той или иной группы. Члены разных групп могут иметь разные права по
доступу к файлам, например, группа администраторов может иметь больше прав, чем
группа программистов.
В индексном дескрипторе каждого файла записаны имя так называемого
владельца файла и группы, которая имеет права на этот файл. Первоначально, при
создании файла его владельцем объявляется тот пользователь, который этот файл создал.
Точнее — тот пользователь, от чьего имени запущен процесс, создающий файл. Группа
тоже назначается при создании файла — по идентификатору группы процесса,
создающего файл. Владельца и группу файла можно поменять в ходе дальнейшей работы
с помощью команд chown и chgrp (подробнее о них будет сказано чуть позже).
Выполнив команду ls –l рассмотрим листинг
[user]$ ls -l /bin/ls
-rwxr-xr-x 1 root root 49940 Sep 12 1999 /bin/ls
В данном случае владельцем файла является пользователь root и группа root.
Первое поле в выводе показывает тип файла и права доступа к файлу. Это поле в
приведенном примере представлено цепочкой символов -rwxr-xr-x. Эти символы можно
условно разделить на 4 группы.
Первая группа, состоящая из единственного символа, определяет тип файла. Этот
символ в соответствии с возможными типами файлов, рассмотренными в предыдущем
разделе, может принимать такие значения:

- — обычный файл;

d — каталог;

b — файл блочного устройства;

c — файл символьного устройства;

s — доменное гнездо (socket);

p — именованный канал (pipe);

l — символическая ссылка (link).
Далее следуют три группы по три символа, которые и определяют права доступа к
файлу соответственно для владельца файла, для группы пользователей, которая
сопоставлена данному файлу, и для всех остальных пользователей системы. В примере
права доступа для владельца определены как rwx, что означает, что владелец (root) имеет
право читать файл (r), производить запись в этот файл (w), и запускать файл на
выполнение (x). Замена любого из этих символов прочерком будет означать, что
пользователь лишается соответствующего права. В том же примере видно, что все
остальные пользователи (включая и тех, которые вошли в группу root) лишены права
записи в этот файл, т. е. не могут файл редактировать и вообще как-то изменять.
12
Вообще говоря, права доступа и информация о типе файла в UNIX-системах
хранятся в индексных дескрипторах в отдельной структуре, состоящей из двух байтов, т. е.
из 16 бит (это естественно, ведь компьютер оперирует битами, а не символами r, w, x).
Четыре бита из этих 16-ти отведены для кодированной записи о типе файла. Следующие
три бита задают особые свойства исполняемых файлов, о которых мы скажем чуть позже.
И, наконец, оставшиеся 9 бит определяют права доступа к файлу. Эти 9 бит разделяются
на 3 группы по три бита. Первые три бита задают права пользователя, следующие три
бита — права группы, последние 3 бита определяют права всех остальных пользователей
(т. е. всех пользователей, за исключением владельца файла и группы файла).
При этом, если соответствующий бит имеет значение 1, то право предоставляется,
а если он равен 0, то право не предоставляется. В символьной форме записи прав
единица заменяется соответствующим символом (r, w или x), а 0 представляется
прочерком.
Право на чтение (r) файла означает, что пользователь может просматривать
содержимое файла с помощью различных команд просмотра, например,
командой less или с помощью любого текстового редактора. Но, подредактировав
содержимое файла в текстовом редакторе, вы не сможете сохранить изменения в файле
на диске, если не имеете права на запись (w) в этот файл. Право на выполнение (x)
означает, что вы можете загрузить файл в память и попытаться запустить его на
выполнение как исполняемую программу. Конечно, если в действительности файл не
является программой (или скриптом оболочки), то запустить этот файл на выполнение не
удастся, но, с другой стороны, даже если файл действительно является программой, но
право на выполнение для него не установлено, то он тоже не запустится.
Для каталогов тоже определены права доступа, причем они задаются теми же
самыми символами rwx. Рассмотрим пример каталога:
drwxr-xr-x 2 root root 2048 Jun 21 21:11 bin
Естественно, что по отношению к каталогам трактовка понятий "право на чтение",
"право на запись" и "право на выполнение" несколько изменяется. Право на чтение по
отношению к каталогам легко понять, если вспомнить, что каталог — это просто файл,
содержащий список файлов в данном каталоге. Следовательно, если вы имеете право на
чтение каталога, то вы можете просматривать его содержимое (этот самый список файлов
в каталоге). Право на запись тоже понятно — имея такое право, вы сможете создавать и
удалять файлы в этом каталоге, т. е. просто добавлять в каталог или удалять из него
запись, содержащую имя какого-то файла и соответствующие ссылки. Право на
выполнение интуитивно менее понятно. Оно в данном случае означает право переходить
в этот каталог. Если вы, как владелец, хотите дать доступ другим пользователям на
просмотр какого-то файла в своем каталоге, вы должны дать им право доступа в каталог,
т. е. дать им "право на выполнение каталога". Более того, надо дать пользователю право
на выполнение для всех каталогов, стоящих в дереве выше данного каталога. Поэтому в
принципе для всех каталогов по умолчанию устанавливается право на выполнение как
для владельца и группы, так и для всех остальных пользователей. И, уж если вы хотите
закрыть доступ в каталог, то лишите всех пользователей (включая группу) права входить в
этот каталог.
После прочтения предыдущего абзаца может показаться, что право на чтение
каталога не дает ничего нового по сравнению с правом на выполнение. Однако разница в
этих правах все же есть. Если задать только право на выполнение, вы сможете войти в
каталог, но не увидите там ни одного файла (этот эффект особенно наглядно проявляется
13
в том случае, если вы пользуетесь каким-то файловым менеджером, например,
программой Midnight Commander). Если вы имеете право доступа в каком-то из
подкаталогов этого каталога, то вы можете перейти в него (командой cd), но, как
говорится "вслепую", по памяти, потому что списка файлов и подкаталогов текущего
каталога вы не увидите.
Алгоритм проверки прав пользователя при обращении к файлу можно описать
следующим образом. Система вначале проверяет, совпадает ли имя пользователя с
именем владельца файла. Если эти имена совпадают (т. е. владелец обращается к своему
файлу), то проверяется, имеет ли владелец соответствующее право доступа: на чтение, на
запись или на выполнение (не удивляйтесь, суперпользователь может лишить некоторых
прав и владельца файла). Если право такое есть, то соответствующая операция
разрешается. Если же нужного права владелец не имеет, то проверка прав,
предоставляемых через группу или через группу атрибутов доступа для остальных
пользователей, уже даже не проверяются, а пользователю выдается сообщение о
невозможности выполнения затребованного действия (обычно что-то вроде "Permission
denied").
Если имя пользователя, обращающегося к файлу, не совпадает с именем
владельца, то система проверяет, принадлежит ли владелец к группе, которая
сопоставлена данному файлу (далее будем просто называть ее группой файла). Если
принадлежит, то для определения возможности доступа к файлу используются атрибуты,
относящиеся к группе, а на атрибуты для владельца и всех остальных пользователей
внимания не обращается. Если же пользователь не является владельцем файла и не
входит в группу файла, то его права определяются атрибутами для остальных
пользователей. Таким образом, третья группа атрибутов, определяющих права доступа к
файлу, относится ко всем пользователям, кроме владельца файла и пользователей,
входящих в группу файла.
Основываясь на битовом представлении прав доступа используем команду chmod
для изменения прав доступа к файлу. Для этого мы кодируем символ r цифрой 4, символ
w — цифрой 2, а символ x — цифрой 1. Для того, чтобы предоставить пользователям
какой-то набор прав, надо сложить соответствующие цифры. Получив, таким образом,
нужные цифровые значения для владельца файла, для группы файла и для всех остальных
пользователей, задаем эти три цифры в качестве аргумента команды chmod (ставим эти
цифры после имени команды перед вторым аргументом, который задает имя файла).
Например, если надо дать все права владельцу (4+2+1=7), право на чтение и запись —
группе (4+2=6), и не давать никаких прав остальным, то следует дать такую команду:
[user]$ chmod 760 file_name
Также файл может иметь ещё три возможных атрибута, устанавливаемых с
помощью той же команды chmod. Это те самые атрибуты для исполняемых файлов,
которые в индексном дескрипторе файла в двухбайтовой структуре, определяющей права
на файл, занимают позиции 5-7, сразу после кода типа файла.
Первый из этих атрибутов — так называемый "бит смены идентификатора
пользователя". Смысл этого бита состоит в следующем.
Обычно, когда пользователь запускает некоторую программу на выполнение, эта
программа получает те же права доступа к файлам и каталогам, которые имеет
пользователь, запустивший программу. Если же установлен "бит смены идентификатора
пользователя", то программа получит права доступа к файлам и каталогам, которые имеет
владелец файла программы (таким образом, рассматриваемый атрибут лучше называть
14
"битом смены идентификатора владельца"). Это позволяет решать некоторые задачи,
которые иначе было бы трудно выполнить. Самый характерный пример — команда
смены пароля passwd. Все пароли пользователей хранятся в файле /etc/passwd,
владельцем которого является суперпользователь root. Поэтому программы, запущенные
обычными пользователями, в том числе команда passwd, не могут производить запись в
этот файл. А, значит, пользователь как бы не может менять свой собственный пароль. Но
для файла /usr/bin/passwd установлен "бит смены идентификатора владельца", каковым
является пользователь root. Следовательно, программа смены пароля passwd запускается
с правами root и получает право записи в файл /etc/passwd (уже средствами самой
программы обеспечивается то, что пользователь может изменить только одну строку в
этом файле).
Установить "бит смены идентификатора владельца" может суперпользователь с
помощью команды
[root]# chmod +s file_name
Аналогичным образом работает "бит смены идентификатора группы".
Еще один возможный атрибут исполняемого файла — это "бит сохранения
задачи" или "sticky bit" (дословно — "бит прилипчивости"). Этот бит указывает системе,
что после завершения программы надо сохранить ее в оперативной памяти. Удобно
включить этот бит для задач, которые часто вызываются на выполнение, так как в этом
случае экономится время на загрузку программы при каждом новом запуске. Этот атрибут
был необходим на старых моделях компьютеров. На современных быстродействующих
системах он используется редко.
Если используется цифровой вариант задания атрибутов в команде chmod, то
цифровое значение этих атрибутов должно предшествовать цифрам, задающим права
пользователя:
[root]# chmod 4775 file_name
При этом веса этих битов для получения нужного суммарного результата задаются
следующим образом:
 4 — "бит смены идентификатора пользователя",
 2 — "бит смены идентификатора группы",
 1 — "бит сохранения задачи (sticky bit)".
Если какие-то из этих трех битов установлены в 1, то несколько изменяется вывод
команды ls -l в части отображения установленных атрибутов прав доступа. Если
установлен в 1 "бит смены идентификатора пользователя", то символ "x" в группе,
определяющей права владельца файла, заменяется символом "s". Причем, если владелец
имеет право на выполнение файла, то символ "x" заменяется на маленькое "s", а если
владелец не имеет права на выполнение файла (например, файл вообще не
исполняемый), то вместо "x" ставится "S". Аналогичные замены имеют место при задании
"бита смены идентификатора группы", но заменяется символ "x" в группе атрибутов,
задающих права группы. Если равен 1 "бит сохранения задачи (sticky bit)", то заменяется
символ "x" в группе атрибутов, определяющей права для всех остальных пользователей,
причем "x" заменяется символом "t", если все пользователи могут запускать файл на
выполнение, и символом "T", если они такого права не имеют.
Таким образом, хотя в выводе команды ls -l не предусмотрено отдельных
позиций для отображения значений битов смены идентификаторов и бита сохранения
15
задачи, соответствующая информация выводится. Вот небольшой пример того, как это
будет выглядеть:
[root]# ls -l prim1
-rwSrwsrwT 1 user root 12 Dec 18 23:17 prim1
Для файла имеющего структуру, изображенную на рисунке, постройте регулярное
выражение, фильтрующее строки, в которых имя сотрудника начинается на букву
"R".
Само решение будет выглядеть следующим образом:
^[0-9]\{1,4\} R
Ниже приведен пример с несколькими вариантами решений, по образцу
которого можно описать решить поставленной задачи.
В файле query1 выбрать все строки, в которых зарплата составляет целое число
тысяч.
Решение 1:
1. Согласно структуре файла, столбец зарплаты начинается с позиции 60, поэтому подвыражение: "^.\{59\}".
2. Если зарплата составляет целое число тысяч, то в ней содержится одна или
несколько цифр, за которыми следует три нуля - подвыражение: "[0-9]\{1,\}000".
3. Однако возможна (теоретически) зарплата, например "10001", поэтому стоит
позаботиться о том, чтобы следующие за тремя нулями символы были отличны от
значащих цифр. Таких символов может быть сколько угодно, и это условие можно
обеспечить подвыражением: "[^0-9]*".
4. Итоговое регулярное выражение:
5.
"^.\{59\}[0-9]\{1,\}000[^0-9]*"
6. Протокол выполнения:
student@r111wslin01 ~ $ grep "^.\{59\}[0-9]\{1,\}000[^0-9]*" query1
7569 CHRIS
L ALBERTS
MANAGER
RESEARCH
NEW-YORK 3000
7788 DONALD
T SCOTT
ANALYST
RESEARCH
DALLAS
3000
7799 MATTHEW
G FISHER
ANALYST
RESEARCH
NEW-YORK 3000
7839 FRANCIS
A KING
PRESIDENT
ACCOUNTING NEW-YORK 5000
7902 JENNIFER D FORD
ANALYST
RESEARCH
DALLAS
3000
student@r111wslin01 ~ $
Решение 2:
16
1. Поскольку зарплата является последним полем строки файла query1, возможно,
можно просто потребовать, чтобы три нуля были последними символами строки и
сформулировать регулярное выражение таким образом: "000$". Однако, такое
решение может наткнуться на неочевидное препятствие. Все зависит от того,
какими средствами был подготовлен исходный файл query1 (особенно, если он
был
перенесен
из
другой
системы).
Дело в том, что разные программы и редакторы используют разные способы
перевода строки, и в конце строки могут оказаться некоторые дополнительные
(невидимые "невооруженным глазом" символы. Таким образом, последний 0 в
зарплате может еще не быть последним символом строки. Как правило, увидеть
эти дополнительные символы можно, выполнив команду cat с опцией -v. В этом
случае на выдаче команды cat можно увидеть непечатный символ, показываемый,
например, как: "^M".
2. Следующие протокол иллюстрирует этот случай:
student@r111wslin01 ~ $ grep "000$" query1
student@r111wslin01 ~ $ cat -v query1
7369 JOHN
Q SMITH
CLERK
RESEARCH
7499 KEVIN
J ALLEN
SALESPERSON SALES
7505 JEAN
K DOYLE
MANAGER
SALES
7506 LYNN
S DENNIS
MANAGER
SALES
7507 LESLIE
D BAKER
MANAGER
OPERATIONS
7521 CYNTHIA
D WARD
SALESPERSON SALES
7555 DANIEL
T PETERS
SALESPERSON SALES
7557 KAREN
P SHAW
SALESPERSON SALES
7560 SARAH
S DUNCAN
SALESPERSON SALES
7564 GREGORY
J LANGE
SALESPERSON SALES
7566 TERRY
M JONES
MANAGER
RESEARCH
7569 CHRIS
L ALBERTS
MANAGER
RESEARCH
7600 RAYMOND
Y PORTER
SALESPERSON SALES
7609 RICHARD
M LEWIS
STAFF
OPERATIONS
7654 KENNETH
J MARTIN
SALESPERSON SALES
7676 DENISE
D SOMMERS
STAFF
OPERATIONS
7698 MARION
S BLAKE
MANAGER
SALES
7782 CAROL
F CLARK
MANAGER
ACCOUNTING
7788 DONALD
T SCOTT
ANALYST
RESEARCH
7789 LIVIA
N WEST
SALESPERSON SALES
7799 MATTHEW
G FISHER
ANALYST
RESEARCH
7820 PAUL
S ROSS
SALESPERSON SALES
7839 FRANCIS
A KING
PRESIDENT
ACCOUNTING
7876 DIANE
G ADAMS
CLERK
RESEARCH
7900 FRED
S JAMES
CLERK
SALES
7902 JENNIFER D FORD
ANALYST
RESEARCH
7916 GRACE
M ROBERTS
ANALYST
RESEARCH
7919 MICHAEL
A DOUGLAS
CLERK
RESEARCH
7934 BARBARA
M MILLER
CLERK
ACCOUNTING
7950 ALICE
B JENSEN
CLERK
SALES
7954 JAMES
T MURRAY
CLERK
SALES
student@r111wslin01 ~ $
DALLAS
CHICAGO
NEW-YORK
DALLAS
NEW-YORK
CHICAGO
NEW-YORK
NEW-YORK
DALLAS
DALLAS
DALLAS
NEW-YORK
NEW-YORK
DALLAS
CHICAGO
CHICAGO
CHICAGO
NEW-YORK
DALLAS
DALLAS
NEW-YORK
BOSTON
NEW-YORK
DALLAS
CHICAGO
DALLAS
NEW-YORK
NEW-YORK
NEW-YORK
NEW-YORK
DALLAS
800^M
1600^M
2850^M
2750^M
2200^M
1250^M
1250^M
1250^M
1250^M
1250^M
2975^M
3000^M
1250^M
1800^M
1250^M
1850^M
2850^M
2450^M
3000^M
1500^M
3000^M
1300^M
5000^M
1100^M
950^M
3000^M
2875^M
800^M
1300^M
750^M
750^M
Решение 3:
17
1. Уточним логику предыдущего решения, оказавшегося неправильным. За тремя
нулями перед концом строки может следовать (а может и не следовать) еще один
символ, отличный от значащей цифры:
2.
"000[^0-9]\{0,1\}"
3. Протокол выполнения:
student@r111wslin01 ~ $ grep "000[^0-9]\{0,1\}" query1
7569 CHRIS
L ALBERTS
MANAGER
RESEARCH
NEW-YORK
7788 DONALD
T SCOTT
ANALYST
RESEARCH
DALLAS
7799 MATTHEW
G FISHER
ANALYST
RESEARCH
NEW-YORK
7839 FRANCIS
A KING
PRESIDENT
ACCOUNTING NEW-YORK
7902 JENNIFER D FORD
ANALYST
RESEARCH
DALLAS
student@r111wslin01 ~ $
3000
3000
3000
5000
3000
18
Download