Скачать презентацию Лекция 1 7 Файловая система Операционные системы и Скачать презентацию Лекция 1 7 Файловая система Операционные системы и

OS&SP_Part1.7_Files.pptx

  • Количество слайдов: 114

Лекция 1. 7: Файловая система Операционные системы и системное программирование Часть 1 Лекция 1. 7: Файловая система Операционные системы и системное программирование Часть 1

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

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

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

Древовидная структура • Файлы в Unix системах организуются в древовидной структуре называемой Файловой системой. Древовидная структура • Файлы в Unix системах организуются в древовидной структуре называемой Файловой системой. Говорят что файловая система это набор файлов и каталогов в формальном виде и допустимой иерархии. Каждый файл имеет имя, определяющее его расположение в файловой системе. • Корнем этого дерева является корневой каталог. Его имя ‘ / ’ • Все файлы имеют имена, которые представляют собой путь (список каталогов который необходимо пройти, чтобы достигнуть файла). • Пример: • /home/stud/prog 1. c • • Имя, начинающееся с / называют полным именем файла. Можно указать относительное имя файла тогда поиск будет начат от текущего каталога.

Метаданные • Важно, что имя файла является атрибутом файловой системы, а не набора данных, Метаданные • Важно, что имя файла является атрибутом файловой системы, а не набора данных, на каком то носителе. Каждый файл имеет метаданные для связи с ним. • Метаданные – набор данных определяющих характер файла. • Они хранятся в индексных дескрипторах, и имя файла в файловой системе является указателем на индексный дескриптор inode.

Типы файлов В операционной системе Unix такие типы: • 1 обычный файл • 2 Типы файлов В операционной системе Unix такие типы: • 1 обычный файл • 2 каталог • 3 файлы устройства • 4 файлы символичной связи (ссылки) • 5 файлы именованных каналов (каналов FIFO) • 6 сокеты • * 3 -6 являются специальными типами

Обозначение типов файл d каталог p FIFO b блочно ориентированное устройств ввода вывода. • Обозначение типов файл d каталог p FIFO b блочно ориентированное устройств ввода вывода. • с символьно ориентированное устройство ввода вывода. • •

Обычные файлы • Он содержит байты данных организованных в линейный массив который называется патокам Обычные файлы • Он содержит байты данных организованных в линейный массив который называется патокам байт. • Байты могут иметь любые значения и следовать в нутрии файла в любом порядке. На системном уровне от обычных файлов не требуется никакой структуризации. Любой байт из файла можно считать и в любой байт можно записать значение. Выполнение операций с файлом начинается на определенном байте, представлявшем месторасположение в нутрии файла. Это местоположение называется позицией в файле или смещением в файле. С каждым открытым файлом операционная система связывает позицию и когда файл открывается впервые позиция в файле равна 0. Переместить позицию можно находясь за концом файла и в эту позицию произвести запись данных, при этом пропущенные не занятые места заполнятся нулями. Но нельзя сместить позицию файла за начало

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

Работа с обычным файлом • Один и тот же файл может быть открыт несколько Работа с обычным файлом • Один и тот же файл может быть открыт несколько раз, причем другими или тем же самым процессом каждое открытие экземпляра файла присваивает уникальный дескриптор файла. Несколько процессов могут использовать один и тот же дескриптор файлов. Работа с файлом производится через индексный дескриптор.

Каталоги • Каталоги это файлы содержащие имена находящихся в них файлов и указатели (номера) Каталоги • Каталоги это файлы содержащие имена находящихся в них файлов и указатели (номера) индексных дескрипторов в которых содержится информация о файле. • Каталоги определяют положение файла в дереве файловой системы. Программа, имеющая право на чтение каталога может прочесть его содержимое, но только системные вызовы ядра имеют право на запись в каталог. Пример: Ø. корневой каталог Ø. . –родительский каталог

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

Пример полного пути /home/std 1 3071. 4534. . 484 f 1. c 4091 prog Пример полного пути /home/std 1 3071. 4534. . 484 f 1. c 4091 prog 1. c 3544 file. txt /home/stud 2 5711. 4534. . 3782 t 1. c 1547 tile. txt 4091 prog 2. c

Файлы символичной связи • Файлы символичной связи выглядят как обычные файлы. Они имеют свой Файлы символичной связи • Файлы символичной связи выглядят как обычные файлы. Они имеют свой индексный дескриптор, а данные хранящееся в нем представляют собой путь к некоторому файлу и тогда обращение к нему приводит к переадресации на файл, который указан в теле файла символом связи.

Файлы устройства • Доступ к устройствам в Unix осуществляется через файлы устройства, которые ведут Файлы устройства • Доступ к устройствам в Unix осуществляется через файлы устройства, которые ведут себя и выглядят как обычные файлы, находящиеся в файловой системе. Его можно открывать читать и записывать в них данные и таким образом взаимодействовать. Ø - Блочные(Block device) Ø - Символьные(character device) • Доступ к символьным устройствам осуществляется как к линейной очереди байтов (клавиатура принтер и т. д. ). Блочные устройства предоставляют возможность обращения к данным как к массивам. То есть имеется возможность поиска данных по массиву. И пользовательские программы могут производить запись и могут читать данные из произвольной области массива (жесткий диск, флешь память и т. д. )

Именованные каналы Работают по принципу FIFO(первый вошел, первый вышел). Представляют собой механизм межпроцесного взаимодействия. Именованные каналы Работают по принципу FIFO(первый вошел, первый вышел). Представляют собой механизм межпроцесного взаимодействия.

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

Договор по конфигурации каталогов в Unix Существует определенный договор по конфигурации каталогов в Unix. Договор по конфигурации каталогов в Unix Существует определенный договор по конфигурации каталогов в Unix. Договор о названии и их смысловом назначении: • • /bin утилиты, требуемые при загрузке системы и используемые пользователем. • /sbin – похож на bin, но здесь находятся команды, не предназначенные для пользователя с общими правами. • /etc – содержит различные конфигурационные файлы. • /etc/passwd • /etc/group • /etc/shells • /etc/termcap • /root личный каталог администратора системы. • /lib – библиотека каталогов используемых программой. • /dev – файлы устройств. • /tmp – каталог для хранения временных файлов. • /boot – файлы, используемые начальным загрузчиком системы. • /usr – содержит подкаталоги различных сервисных подсистем. • /usr/bin – команды. • /usr/sbin – команды используемые администратором системы. • /usr/lib – файлы данных для программ, включая некоторые конфигурационные файлы. • /usr/local – отдельно размещенные пакеты программ и другие файлы. • /home – домашний каталог пользователя.

Владельцы файлов и права доступа к файлу • Все файлы в Unix имеют двух Владельцы файлов и права доступа к файлу • Все файлы в Unix имеют двух владельцев (пользователь и группа пользователей). • Права на файл назначаются владельцем файла. Владельцем созданного файла назначается идентификатор пользователя того процесса который создал файл. Правило назначения группы: в большинстве ОС группой владельцем становится первичная группа пользователя, которая инициировала создание файла. Владение файлом определяют набор операций, которые пользователь может совершить с файлом. Некоторые действия над файлом (изменение прав доступа или изменение владельца файла) может определять только владелец файла или root. Но ряд других операций (чтение, запись) отдельно определены для разных категорий пользователей.

3 базовых класса В ОС Unix существует три базовых класса доступа к файлу: • 3 базовых класса В ОС Unix существует три базовых класса доступа к файлу: • - пользователь, владеющий файлом; • - пользователь, относящийся к группе владеющей файлом; • - остальные (остальные кроме root). И для каждого класса устанавливаются 3 типа прав доступа: • - чтение; • - запись; • - выполнение.

Обозначение привелегий • Для просмотра содержимого необходимо r. • Для изменения содержимого необходимо w. Обозначение привелегий • Для просмотра содержимого необходимо r. • Для изменения содержимого необходимо w. • Для запуска на выполнение необходимо x.

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

Порядок действия ОС при проверке прав доступа • Если это root действие разрешается и Порядок действия ОС при проверке прав доступа • Если это root действие разрешается и дополнительной проверки не производится. • Если действие запрашивается владельцем файла, то проверяется наличие права на запрашиваемое действие. • Если действие запрашивается пользователем, входящим в группу владеющую файлом, то проверяется наличие права на запрашиваемое действие. • Если действие запрашивается другим пользователем, то проверяется наличие права на запрашиваемое действие.

Дополнительные атрибуты файла Код Название Описание T stickybit S set. UID S set. GID Дополнительные атрибуты файла Код Название Описание T stickybit S set. UID S set. GID Требует сохранение образа выполняемого файла в памяти после завершения выполнения. Это имеет важное значение по отношению к каталогам. Он позволяет удалять пользователю только те файлы, которыми он владеет или имеет права w. По отношению к пользовательскому идентификатору. Он позволяет изменить права пользователя при запуске на выполнение файла имеющего эти атрибуты. При этом привилегии будут изменены лишь на время выполнения и только для этой программы. Обычно она получает права доступа к системным ресурсам на основе прав доступа пользователя запустившего программу. Установка s изменяет это правило назначения права доступа исходя из прав доступа владельца файла. Серьезного смысла не имеет, но по отношению к каталогу установка S приведет к тому, что файлы, созданные в таком каталоге, будут наследовать владельца группы по владельцу группы каталога.

Файловый ввод/вывод Перед тем как выполнять операцию чтения или записи в файл, его необходимо Файловый ввод/вывод Перед тем как выполнять операцию чтения или записи в файл, его необходимо открыть. Ядро ОС ведет списки открытых файлов для всех процессов. Эти списки называют таблицами файлов (file table). Они индексируются при помощи неотрицательных целых значений, называемых файловыми дескрипторами (file descriptor, fd). Каждая запись в списке содержит информацию об открытом файле, включая указатель на находящуюся в памяти копию индексного дескриптора (inode) и связанные метаданные: позицию в файле и режимы доступа. Пользовательское пространство и пространство ядра ОС использует файловые дескрипторы в качестве уникальных для каждого процесса маркеров. При открытии файла возвращается файловый дескриптор (точнее номер), а последующие операторы над файлом принимают файловый дескриптор как основной аргумент.

Файловые дескрипторы • файлом принимают файловый дескриптор как основной аргумент. • Файловые дескрипторы представляются Файловые дескрипторы • файлом принимают файловый дескриптор как основной аргумент. • Файловые дескрипторы представляются типом int. У каждого процесса есть максимальное число файлов, которое он может открыть. Номер файлового дескриптора начинается с 0. По умолчанию максимальное число файлов, которое может открыть процесс, 1024. Таким образом, значения файловых дескрипторов колеблются в пределах 0. . 1023.

3 открытых дескриптора • Каждый процесс при создании имеет по крайней мере три открытых 3 открытых дескриптора • Каждый процесс при создании имеет по крайней мере три открытых дескриптора: 0, 1, 2, которые определяют соответственно стандартный ввод (standart in, stdin), стандартный вывод (standart out, stdout) и дескриптор стандартного вывода ошибочных ситуаций (standart error, stderr): Ø STDIN_FILEND – 0 Ø STDOUT_FILEND – 1 Ø STDERR_FILEND – 2

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

Открытие файла Для начала работы с файлом его необходимо открыть. Для этого существует специальный Открытие файла Для начала работы с файлом его необходимо открыть. Для этого существует специальный системный вызов open: • #include • #include • #include • int open(const char *name, int flags); • int open(const char *name, int flags, mode_l mode);

open Данный системный вызов использует первый параметр name как полный путь к файлу и open Данный системный вызов использует первый параметр name как полный путь к файлу и сопоставляет с этим именем дескриптор файла, который возвращается при успешном завершении операции. Позиция в файле устанавливается в 0, а разрешение на доступ к файлу определяется вторым параметром flags.

flags может принимать следующие значения: • O_RDONLY – только для чтения • O_WRONLY – flags может принимать следующие значения: • O_RDONLY – только для чтения • O_WRONLY – только для записи • O_RDWR – и чтение, и запись

Пример использования системного вызова open с проверкой: int fd; fd=open(“/home/stud/file 1”, O_RDONLY); if (fd==-1) Пример использования системного вызова open с проверкой: int fd; fd=open(“/home/stud/file 1”, O_RDONLY); if (fd==-1) { //обработка ошибки }

Чтение из файла • Системный вызов read(), объявленный в файле unistd. h, позволяет читать Чтение из файла • Системный вызов read(), объявленный в файле unistd. h, позволяет читать данные из файла. • Системный вызов read() читает данные в "сыром" виде, то есть как последовательность байт, без какой либо интерпретации. • ssize_t read (int fd, void * buffer, size_t count); • Первый аргумент это файловый дескриптор. Здесь больше сказать нечего. Второй аргумент это указатель на область памяти, куда будут помещаться данные. Третий аргумент количество байт, которые функция read() будет пытаться прочитать из файла. Возвращаемое значение количество прочитанных байт, если чтение состоялось и 1, если произошла ошибка.

Запись в файл • Для записи данных в файл используется системный вызов write(). • Запись в файл • Для записи данных в файл используется системный вызов write(). • ssize_t write (int fd, const void * buffer, size_t count); • Записывает count байтов из буфера buffer в файл с дескриптором fd, возвращая количество записанных байтов или 1 в случае ошибки.

Закрытие файла • Системный вызов close() закрывает файл. Вообще говоря, по завершении процесса все Закрытие файла • Системный вызов close() закрывает файл. Вообще говоря, по завершении процесса все открытые файлы (кроме файлов с дескрипторами 0, 1 и 2) автоматически закрываются. Тем не менее, это не освобождает нас от самостоятельного вызова close(), когда файл нужно закрыть. К тому же, если файлы не закрывать самостоятельно, то соответствующие дескрипторы не освобождаются, что может привести к превышению лимита открытых файлов.

Что можно делать с файлом? Над файлом можно выполнять только разрешенные параметром flags действия. Что можно делать с файлом? Над файлом можно выполнять только разрешенные параметром flags действия. Процесс, который выполняет открытие, должен иметь соответственные права доступа.

Дополнительные флаги Также есть и дополнительные флаги, которые могут присоединяться операцией ИЛИ с основными: Дополнительные флаги Также есть и дополнительные флаги, которые могут присоединяться операцией ИЛИ с основными: • O_APPEND – файл открыт в режиме присоединения, перед каждой записью указатель позиции устанавливается в конец файла; • O_CREAT – если файл name не существует, то он создается, если же файл существует и помимо CREAT используется EXCL, то open завершается с ошибкой (возвращается 1); • O_EXCL – этот флаг совместно с CREAT используется для предотвращения повторного создания файла; • O_SYNC – файл открывается для синхронного ввода/вывода, при этом ни одна операция записи не будет завершена, пока данные физически не будут записаны на диск; • O_NONBLOCK – файл открывается в режиме без блокировки, если это возможно. Т. е. ни вызов open, ни любые другие вызовы не приводят к блокировке (засыпанию) процесса во время ввода вывода. Флаг определен только для конвейеров FIFO; • O_TRUNC – при использовании этого флага, если файл существует и это обычный файл, он усекается до нулевой длины, запись в него допускается.

Примером использования системного вызова open с дополнительными флагами fd=open(“/home/stud/file. rot”, O_WRONLY|O_TRUNC); Примером использования системного вызова open с дополнительными флагами fd=open(“/home/stud/file. rot”, O_WRONLY|O_TRUNC);

Мультиплексированный ввод/вывод позволяет программе одновременно фиксироваться на нескольких файловых дескрипторах и получать уведомления, когда Мультиплексированный ввод/вывод позволяет программе одновременно фиксироваться на нескольких файловых дескрипторах и получать уведомления, когда один или несколько из них становятся доступными для чтения или для записи без блокировки. • #include • #include • #include • int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

select Системный вызов select позволяет получить информацию о состоянии файловых дескрипторов, используя тип fd_set, select Системный вызов select позволяет получить информацию о состоянии файловых дескрипторов, используя тип fd_set, который определяет набор файловых дескрипторов. В системном вызове в качестве параметров указаны три параметра данного типа (а именно набор файловых дескрипторов, в которых ожидается момент доступности для чтения, readfds, или для записи, writefds, для сокетов – определяется исключительная ситуация, exceptfds). Первый параметр определяет значение файлового дескриптора, который на единицу больше, чем максимальное значение файлового дескриптора, состояние которого будет анализироваться. Последний параметр определяет время для анализа ситуации по файловым дескрипторам, если указатель NULL, то системный вызов сразу же возвратит значение, если же явно задано время в секундах и микросекундах, то на протяжении этого времени анализируется ситуация, после чего выдается значение. Структура, которая представляет время следующая: • struct timeval • { long tv_sec; • long tv_usec; }

Специальные макросы для работы с наборами файловых дескрипторов • • FD_CLR(int fd, fd_set *set); Специальные макросы для работы с наборами файловых дескрипторов • • FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_ZERO(fd_set *set);

FD_CLR • макрос устанавливает 0 в значение файлового дескриптора fd из заданного набора дескрипторов FD_CLR • макрос устанавливает 0 в значение файлового дескриптора fd из заданного набора дескрипторов

FD_ISSET • второй – проверяет, включен ли файловый дескриптор в набор FD_ISSET • второй – проверяет, включен ли файловый дескриптор в набор

FD_SET • добавляет в набор файловый дескриптор FD_SET • добавляет в набор файловый дескриптор

FD_ZERO • обнуляет набор файловых дескрипторов FD_ZERO • обнуляет набор файловых дескрипторов

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

Ошибки макросов При ошибке возвращается 1 и переменная errno принимает одно из следующих значений: Ошибки макросов При ошибке возвращается 1 и переменная errno принимает одно из следующих значений: • EBADF – в одном из наборов содержится недопустимый дескриптор • EINTR – во время ожидания был получен сигнал • EINVAL – указанное значение тайм аута недопустимо • ENOMEM – недостаточно памяти для выполнения запроса

 • • • • • • • • • • #include <sys/time. h> • • • • • • • • • • #include #include #include #include #define TIMEOUT 2 #define BUF_LEN 1024 Пример работы select int main(void) { struct timeval tv; fd_set readfds; int ret; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); tv. tv_sec=TIMEOUT; tv. tv_usec=0; ret=select(STDIN_FILENO+1, &readfds, NULL, &tv); // проверяем можно ли читать с ввода/вывода if (ret==-1) { perror(“select”); return(1); } else if (!ret) { printf(“%d секунд прошлиn”, TIMEOUT; return(0); } if (FD_ISSET(STDIN_FILENO, &readfds)) // проверяем для ожидаемого файлового дескриптора { char buf[BUF_LEN+1]; int len; len=read(STDIN_FILENO, buf, BUF_LEN); if (len==-1) { perror(“read”); return(1); } if (len) { buf[len]=’’; printf(“read: %sn”, buf); } return(0); } else printf(“Такое невероятно !n”); return (1); }

Следующий системный вызов poll Следующий системный вызов проверяет файловые дескрипторы и права доступа (возможность Следующий системный вызов poll Следующий системный вызов проверяет файловые дескрипторы и права доступа (возможность работы). Файловые дескрипторы находятся в массиве, который определен первым параметром вызова. • • #include • int poll(struct pollfd *fds, unsigned int nfds, int timeout);

Структура pollfd Каждый элемент определяет такую структуру: первый элемент – номер дескриптора, второй – Структура pollfd Каждый элемент определяет такую структуру: первый элемент – номер дескриптора, второй – какие события должны наблюдаться для этого файла, третий же параметр – события, какие реально присущи файлу. • struct pollfd • { int fd; • short events; • short revents; }

Поля events, revents определены битовыми масками: • POLLIN – есть данные для чтения • Поля events, revents определены битовыми масками: • POLLIN – есть данные для чтения • POLLRDNORM – есть обычные данные для чтения • POLLRDBAND – есть приоритетные данные для чтения • POLLPRI – есть срочные данные для чтения • POLLOUT – операция записи не заблокируется • POLLWRNORM – операция записи обычных данных не заблокируется • POLLWRBAND – запись приоритетных данных не заблокируется • POLLMSG –доступно сообщение SIGPOLL В качестве возвращаемых событий: • POLLER – ошибка в указанном дескрипторах • POLLHUR – зависшее событие для данного дескриптора • POLLNVAL – дескриптор файла не допустим

nfds • это сколько элементов массива наблюдается nfds • это сколько элементов массива наблюдается

timeout • Третий параметр определяет длину, ожидающую в миллисекундах (мс), когда интервал времени истекает, timeout • Третий параметр определяет длину, ожидающую в миллисекундах (мс), когда интервал времени истекает, вызов возвращает значение, даже если дескриптор к вводу/выводу не обнаружены. Если этот параметр равен 0, то вызов возвращает значение немедленно.

return При успешном завершении системный вызов возвращается число дескрипторов, у которых revents не равно return При успешном завершении системный вызов возвращается число дескрипторов, у которых revents не равно 0. Если их нет return(0) при ошибке – ( 1). Ошибочные ситуации, значения которых заносятся в ERRNO: • EBADF – недопустимый дескриптор файла • EFAULT – указывается на fds, находящиеся за пределами адресного пространства • EINTR – получен сигнал до истечения времени • EINVAL – второй параметр больше чем значение • ENOMEN – нехватка памяти для выполнения запроса

Пример системного вызова poll • • • • • • • #include <sys/poll. h> Пример системного вызова poll • • • • • • • #include #include #include #define TIMEOUT 2 int main(void) { struct pollfd fds[2]; int ret; fds[0]. fd=STDIN_FILENO; fds[0]. events=POLLIN; fds[1]. fd=STDOUT_FILENO; fds[1]. events=POLLOUT; // задание файловых дескрипторов и событий, которые ожидаются ret=poll(fds, 2, TIMEOUT*1000); // проверяются файловые дескрипторы, которые заданы if (ret==-1) { perror(“poll”); return(1); } if (!ret) { printf(“%d секунд истеклиn”, TIMEOUT); return(0); } if (fds[0]. revents & POLLIN) { printf(“stdin доступен на чтение n”); } if (fds[1]. revents & POLLOUT) { printf(“stdout доступен для записи n”); } return(0); }

Системные вызовы для получения значений метаданных файла • • • #include <sys/types. h> #include Системные вызовы для получения значений метаданных файла • • • #include #include #include int stat(const char *path, struct stat *buf); int fstst(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf); Где параметр path – это полный путь к файлу, а fd – открытый файловый дескриптор. Системный вызов lstat отличается от stat тем, что он позволяет получить информацию о файле типа символьная ссылка. При успешном завершении вызовов возвращается 0 и в структуру stat помещаются метаданные, а при ошибке возвращается значение 1 и устанавливаются коды ошибок.

struct stat • • • • • struct stat { dev_t st_dev; //устройство, на struct stat • • • • • struct stat { dev_t st_dev; //устройство, на котором хранится файл ino_t st_ino; //номер inode (индексного дескриптора) mode_t st_mode; //режимы использования файла nlink_t st_nlink; //число жестких ссылок uid_t st_uid; //идентификатор пользователя владельца gid_t st_gid; //идентификатор группы владельца dev_t st_rdev; //если этот файл – устройство, то описано устройство, которое файл представляет off_t st_size; //размер файла в байтах blksize_t st_blksize; //размер блока для эффективной реализации ввода/вывода blkcnt_ st_blocks; //число блоков физической файловой системы, которое занимает файл time_t st_atime; //время последнего доступа к файлу time_t st_mtime; //время последней модификации метаданных файла time_t st_ctime; //время последней изменения файла }

Возможные ошибки системного вызова state • EACCESS – у вызывающего процесса отсутствуют разрешения на Возможные ошибки системного вызова state • EACCESS – у вызывающего процесса отсутствуют разрешения на поиск для одного из каталогов в пути path (только для функций stat () и lstat ()). • EBADF – недопустимое значение fd (только для функции fstat()). • EFAULT – параметр path или buf содержит недопустимый указатель. • ELOOP – параметр path включает слишком много символических ссылок (только для функций stat() и Istat()). • ENAMETOOLONG – слишком длинное значение параметра path (только для функций stat() и Istat()). • ENOENT – компонент пути path не существует (только для функций stat() и Istat()). • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOTDIR – компонент пути path не является каталогом (только для функций stat() и Istat()).

 • • • • • • Пример вызова для получения метаданных #include <sys/types. • • • • • • Пример вызова для получения метаданных #include #include #include static short o_ar[9]={0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001} static char perms[10]= “rwxrwxrwx” int filedata(const char *pathname) { struct statbuf; char d[10]; int j; if (stat(pathname, &statbuf)==-1) { printf(“Ошибка stat %sn”, pathname); return(-1); } for (j=0; j<9; j++) { if (statbuf. st_mode & o_ar[j]) d[j]=perms[j]; else d[j]=’-’; } d[9]=’’; printf(“файл %s : n”, pathname); printf(“размер %ld байт n”, statbuf. st_size); printf(“User_id %d, Group_id %dn”, statbuf. st_uid, statbuf. st_gid); printf(“Права доступа: %sn”, d); return(0); }

st_mode может принимать значения: • S_ISDIR каталог • S_ISCHR символьное устройство • S_ISBLK – st_mode может принимать значения: • S_ISDIR каталог • S_ISCHR символьное устройство • S_ISBLK – блочное устройство • S_ISREG – простой файл • S_ISFIFO канал • S_ISLINK – ссылка • S_ISSOCK – сокет

Системные вызовы для изменения права доступа к файлу • • #include <sys/types. h> #include Системные вызовы для изменения права доступа к файлу • • #include #include int chmod(const char *path, mode_t mode); int fcmod(int fd, mode_t mode);

chmod и fchmod Оба вызова chmod() и fchmod() устанавливают для файла разрешения, указан ные chmod и fchmod Оба вызова chmod() и fchmod() устанавливают для файла разрешения, указан ные при помощи параметра mode. В вызове chmod() параметр path содержит отно сительный или абсолютный путь к модифицируемому файлу. Для вызова fсhmod() файл указывается при помощи дескриптора fd.

Ошибки chmod • EACCESS – у вызывающего процесса нет разрешений на поиск для компонента Ошибки chmod • EACCESS – у вызывающего процесса нет разрешений на поиск для компонента пути path (только для chmod()). • EBADF – недопустимый дескриптор файла fd (только для fchmod()). • EFAULT – параметр path содержит недопустимый указатель (только для chmod()). • EIO – в файловой системе произошла внутренняя ошибка ввода вывода. Это очень плохая ситуация, которая может указывать на повреждение диска или файловой системы. • ELOOP – во время разрешения пути path ядро встретило слишком много символиче ских ссылок (только для hmod()). c • ENAMETOOLONG – слишком длинное значение параметра path (только для chmod()). • ENOENT – путь path не существует (только для параметра chmod(). • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOTDIR – компонент пути path не является каталогом (только для chmod()). • EPERM – действительный идентификатор вызывающего процесса не соответствует владельцу файла, и у процесса отсутствует характеристика CAP_FOWNER. • EROFS – файл находится в файловой системе, доступной только для чтения.

Системные вызовы для смены владельца • #include <sys/types. h> • #include <unistd. h> • Системные вызовы для смены владельца • #include • #include • int chown (const char *path, uid_t owner, gid_t group); • int lchown (const char *path, uid_t owner, gid_t group); • int fchown (int fd, uid_t owner, gid_t group): ,

chown и Ichown • Вызовы chown() и Ichown() определяют владение файлом, указанным при по chown и Ichown • Вызовы chown() и Ichown() определяют владение файлом, указанным при по мощи пути в параметре path. Они работают одинаково для всех файлов, за исключением символических ссылок. • В случае успеха все три вызова делают владельцем файла пользователя owner, группой файла группу group и возвращают значение 0. Если параметр owner или group равен 1, то соответствующее значение не устанавливается. Только процесс, владеющий характеристикой CAP_CH 0 WN (обычно это процесс, принадлежащий пользователю root), может менять владельца файла. Владелец файла может сменить группу файла на любую другую, членом которой он явля ется; процессы с характеристикой CAP_CH 0 WN имеют право менять группу файла на любое другое значение.

Ошибки chown В случае ошибки вызовы возвращают 1 и присваивают переменной errno одно из Ошибки chown В случае ошибки вызовы возвращают 1 и присваивают переменной errno одно из следующих значений: • EACCESS – у вызывающего процесса отсутствуют разрешения на поиск для компонента пути path (только для chown() и Ichown()). • EBADF – недопустимое значение fd (только для fchown()). • EFAULT – недопустимое значение path (только для chown() и Ichown()). • EIO – внутренняя ошибка ввода вывода. • ELOOP – во время разрешения пути path ядро встретило слишком много символиче ских ссылок (только для hown() и Ichown()). c • ENAMETOOLONG – слишком длинное значение path (только для chown() и Ichown()). • ENOENT – файл не существует. • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOTDIR – компонент пути path не является каталогом (только для chown() и lchown()). • EPERM – у вызывающего процесса отсутствуют необходимые права для изменения владельца или группы в соответствии с запросом. • EROFS – файловая система доступна только для чтения.

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

Текущий каталог Каждый процесс имеет текущий каталог, который наследуется от родительского каталога. Он является Текущий каталог Каждый процесс имеет текущий каталог, который наследуется от родительского каталога. Он является начальной точкой, относительно которой ОС определяет относительные пути к файлу. Программа может определять свой текущий рабочий каталог, используя следующий системный вызов: • #include • char *getcwd(char *buf, size_t size);

Ошибки при получении текущего каталога При успешном выполнении абсолютный путь текущего каталога заносится в Ошибки при получении текущего каталога При успешном выполнении абсолютный путь текущего каталога заносится в буфер (первый аргумент), размер буфера определяется вторым аргументом, и возвращает указатель на буфер, куда заносится полный путь. При ошибке возвращается NULL и устанавливаются ошибки в errno: • EFAULT – параметр buf содержит недопустимый указатель. • EINVAL – значение size равно 0, но значение buf не равно NULL. • ENOENT – текущий рабочий каталог более не действителен. Это может происходить при удалении текущего рабочего каталога. • ЕRANGE – значение size слишком мало, чтобы можно было сохранить текущий рабо чий каталог в буфере uf. Необходимо выделить буфер большего b размера и повторить попытку. • • #define BUF_LEN 256 • char cwd[BUF_LEN]; • if (!getcwd(cwd, BUF_LEN)) • { perror(“getcwd”); • exit(-1); }

Альтернативное использование • Если же указаны нулевые значения buf и BUF_LEN, т. е. сделан Альтернативное использование • Если же указаны нулевые значения buf и BUF_LEN, т. е. сделан такой вызов cwd=getcwd(0, 0); то ОС сама выделяет место под буфер, куда и будет помещено имя рабочего каталога. • При завершении программы желательно всегда освобождать это место с помощью системного вызова: free(cwd).

Изменения текущего каталога Программа может изменять текущий каталог: • #include <unistd. h> • int Изменения текущего каталога Программа может изменять текущий каталог: • #include • int chdir(const char *path); • int fchdir(int fd); • Первый вызов требует новое значение в качестве параметра функции (путь может задаваться абсолютно или относительно), а второй – файловый дескриптор.

Ошибки при смене текущего каталога При ошибке возвращают 1, а при успешном завершении – Ошибки при смене текущего каталога При ошибке возвращают 1, а при успешном завершении – 0. • EACCESS – у вызывающего процесса отсутствуют разрешения на поиск для компонента пути path. • EFAULT – параметр path содержит недопустимый указатель. • EIO – произошла внутренняя ошибка ввода вывода. • ELOOP – во время разрешения пути path ядру встретилось слишком много символи ческих ссылок. • ENAMETOOLONG – слишком длинное значение path. • ENOENT – каталог, на который указывает параметр path, не существует. • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOTDIR – один или несколько компонентов пути path не являются каталогами. fchdiг() может присваивать переменной errno следующие значения: • EACCESS – у вызывающего процесса отсутствуют разрешения на поиск в каталоге с де скриптором файла, указанным при помощи параметра d (то есть f бит испол нения не установлен). Такая ситуация случается, когда каталог более высо кого уровня доступен для чтения, но не для исполнения, вызов pen() o выполняется успешно, но fchdiг() завершается ошибкой. • EBADF – значение параметра fd не является открытым дескриптором файла.

Пример возврата в текущий каталог Программа может изменить сначала свой рабочий каталог, а потом Пример возврата в текущий каталог Программа может изменить сначала свой рабочий каталог, а потом вернуться к старому. Рекомендуется открывать каталог с помощью файлового дескриптора: • int swd_fd; • swd_fd=open(“. ”, O_RDONLY); • if (swd_fd==-1) • { //обработка ошибок • } • ret=chdir(“home/gr 2/stud 2”); • if (ret) • { //обработка ошибок • } • … • ret=fchdir(swd_fd); • if (ret) • { //обработка ошибок • } • ret=close(swd_fd); Такой подход быстрее, т. к. ОС работает только с индексным дескриптором и он заносится в ОП. При возвращении в текущий каталог, его значение задавать не надо, оно берется из ОП.

Создание каталога • #include <unistd. h> • #include <sys/stat. h> • #include <sys/types. h> Создание каталога • #include • #include • #include • int mkdir(const char *path, mode_t mode); Данный системный вызов – это создание каталога, первым параметром в нем задается относительный путь, вторым – режим доступа.

Ошибки при создании каталога Успешный вызов mkdir() создает каталог path (параметр может содержать абсолютный Ошибки при создании каталога Успешный вызов mkdir() создает каталог path (параметр может содержать абсолютный или относительный путь) с битами разрешения mode (как они модифицированы текущим хначением umask) и возвращает значение 0. В случае ошибки mkdir() возвращает 1: • EACCESS – у текущего процесса нет прав на запись в родительский каталог, или один или несколько компонентов в пути path недоступны для поиска. • EEXIST – путь path уже существует (и не обязательно является каталогом). • EFAULT – параметр path содержит недопустимый указатель. • ELOOP – во время разрешения пути path ядру встретилось слишком много символических ссылок. • ENAMETOOLONG – слишком длинное значение path. • ENOENT – компонент пути path не существует или является символической ссылкой указывающей на несуществующий объект. • ENOMEM – недостаточно памяти ядра для выполнения данного запроса. • ENOSPC – на устройстве, где находится path, недостаточно пространства либо превышена дисковая квота для пользователя. • ENOTDIR – один или несколько компонентов пути path не являются каталогами. • EPERM – файловая система, которой принадлежит path, не поддерживает создание каталогов. • EROFS – файловая система, которой принадлежит path, подмонтирована с доступом только на чтение.

Удаление каталога • #include <unistd. h> • #include <sys/stat. h> • #include <sys/types. h> Удаление каталога • #include • #include • #include • int mkdir(const char *path, mode_t mode); • int rmdir(const char *path); Данный системный вызов – удаление каталога, имя которого определяется параметром. При этом необходимо помнить, что задается только условный каталог (в нем не должно быть никаких файлов, только. и. . ).

Ошибки при удалении каталога В случае успеха rmdir() удаляет каталог path из файловой системы Ошибки при удалении каталога В случае успеха rmdir() удаляет каталог path из файловой системы и возвращает значение 0. Каталог, указанный при помощи параметра path, должен быть пустым, за исключением каталогов точка и точка. В случае ошибки возвращает 1 и присваивает переменной errno одно из следующих значений: • EACCESS – запрещен доступ на запись в родительский каталога path или одна или несколько составляющих path недоступны для поиска. • EBUSY – каталог path в данный момент используется системой и удалить его невозможно. В Linux это может произойти только в том случае, если path является точкой монтирования или корневым каталогом (корневые каталоги не обязаны быть точками монтирования). • ЕFAULT – параметр path содержит недопустимый указатель. • EINVAL – последним компонентом пути path является каталог точка. • ELOOP – при разрешении пути path ядру встретилось слишком много символических ссылок. • ENAMETOOLONG – слишком длинное значение path. • ENOENT – компонент пути path не существует или представляет собой символическую ссылку, указывающую на несуществующий объект. • ENOMEM – недостаточно памяти ядра для выполнения данного запроса. • ENOTDIR – один или несколько компонентов пути path не являются каталогами. • ENOTEMPTY – каталог path содержит другие записи, кроме специальных каталогов точка и точка. • EPERM – для каталога, являющегося предком каталога path, установлен бит закрепления в памяти (sticky bit, SISVTX), но действительный идентификатор пользователя процесса не совпадает ни с идентификатором пользователя указанного родителя, ни с идентификатором самого каталога path, а также процесс не обладает характеристикой CAPFOWNER. Также возможно, что файловая система, которой принадлежит path, не поддерживает удаление каталогов. • EROFS – файловая система, которой принадлежит path, подмонтирована в режиме только для чтения.

Чтение информации из каталога Для того чтобы начать читать содержимое каталога, нужно создать поток Чтение информации из каталога Для того чтобы начать читать содержимое каталога, нужно создать поток каталога (directory stream), представляемый объектом DIR: • • #include • #include • DIR *opendir(const char *name); • struct dirent *readdir(DIR *dir); • void rewinddir(DIR *dirptr); • Где структура dirent представлена так: • struct dirent • { ino_t d_ino; • off_t d_off; • unsigned short d_reclen; • unsigned char d_type; • char d_name[256]; }

opendir Системный вызов используется для открытия потока каталога, в качестве параметров которого указывается название opendir Системный вызов используется для открытия потока каталога, в качестве параметров которого указывается название каталога, он возвращает указатель на поток каталога. При успешном выполнении возвращается указатель соответственного типа, при ошибке NULL.

readdir • Системный вызов позволяет читать записи из каталога. В качестве параметра вызова передается readdir • Системный вызов позволяет читать записи из каталога. В качестве параметра вызова передается указатель на дескриптор открытого файла, а возвращается указатель на запись. • В структуре dirent POXIS определяет только поле d_name, остальные поля могут модифицироваться, но в основном они такие: 1) поле идентификатора дескриптора 2) смещение к следующей записи 3) длина данной записи 4) тип файла 5) имя файла • При ошибке системный вызов возвращает NULL. • При каждом выполнении происходит смещение на следующую запись в каталоге (следующее имя файла). При каждом вызове errno нужно устанавливать в 0, а после завершения проверять значение. Пример ошибки, которая может возвратиться: • EBADF – задано недоступное значение аргумента • Это для отличия ситуации, когда доходит до последней записи, и ошибочной ситуации при чтении с каталога.

rewinddir Системный вызов возвращает указатель чтения на первую запись в каталоге. • • #include rewinddir Системный вызов возвращает указатель чтения на первую запись в каталоге. • • #include • #include • struct dirent *d; • DIR *dp; • if ((dp=opendir(name))==NULL) • return(-1); • while (d=readdir(dp)) // • { if (d->d_ino!=0) printf(“%sn”, d->d_name); • } • rewinddir(dp); // • while (d=readdir(dp)) • { if (d->d_ino!=0) printf(“%sn”, d->d_name); • } • close(dp); • return(0); • } Эта программа выводит два раза содержимое каталога (имена файлов в этом каталоге, включая. и. . ). Но нужна дополнительная проверка, чтобы число индексных дескрипторов было отлично от 0.

Закрытие каталога Для закрытия каталога используется встроенный системный вызов: • int closedir(DIR *dir); Успешный Закрытие каталога Для закрытия каталога используется встроенный системный вызов: • int closedir(DIR *dir); Успешный вызов closedir() закрывает поток каталога, переданный при помощи параметра dir, а также соответствующий дескриптор файла и возвращает значение 0. В случае ошибки функция возвращает 1 и присваивает переменной errno значение EBADF – единственный возможный код ошибки, указывающий, что dir не является открытым потоком каталога.

Создание жестких ссылок Можно еще создавать жесткую ссылку или еще одно имя для существующего Создание жестких ссылок Можно еще создавать жесткую ссылку или еще одно имя для существующего файла: • #include • int link(const char *oldpath, const char *newpath); • Для одного и того же файла можно создавать несколько имен: • link(“/home/gr 1/stud 1”, “/home/gr 2/stud 2”);

Пример жестких ссылок Пример жестких ссылок

Ошибки при создании жестких ссылок Успешный вызов link() создает для пути newpath новую ссылку, Ошибки при создании жестких ссылок Успешный вызов link() создает для пути newpath новую ссылку, указывающую на существующий файл oldpath, и возвращает значение 0. После завершения оба пути, oldpath и newpath, указывают на один и тот же файл, то есть, фактически невозможно сказать, какая из ссылок была «исходной» . При ошибке возвращается 1. • EACCESS –у вызывающего процесса отсутствуют разрешения на поиск для компонента пути oldpath или у вызывающего процесса нет разрешений на запись в ката лог, содержащий newpath. • EEXIST – путь newpath уже существует — системный вызов link () не переопределяет существующие записи каталога. • EFAULT – параметр oldpath или newpath содержит недопустимый указатель. • EIO – произошла внутренняя ошибка ввода вывода. • ELOOP – при разрешении пути oldpath или newpath встретилось слишком много сим волических ссылок. • EMLINK – на структуру inode, на которую указывает путь oldpath, уже указывает мак симально допустимое количество ссылок. • ENAMETOOLONG –слишком длинное значение oldpath или newpath. • ENOENT – компонент oldpath или newpath не существует. • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOSPC – на устройстве, которому принадлежит newpath, недостаточно свободного про странства для новой записи каталога. • ENOTDIR – компонент oldpath или newpath не является каталогом. • EPERM – файловая система, которой принадлежит newpath, не допускает создание но вых жестких ссылок или oldpath является каталогом. • EROFS – newpath принадлежит файловой системе, доступной только для чтения. • EXDEV – пути newpath и oldpath не принадлежат одной и той же подмонтированной системе. (Linux допускает монтирование одной файловой системы в не скольких точках, но даже в этом случае нельзя создавать жесткие ссылки ме жду точками монтирования. )

Символическая ссылка • #include <unistd. h> • int symlink(const char *oldpath, const char *newpath); Символическая ссылка • #include • int symlink(const char *oldpath, const char *newpath); Системный вызов, предназначенный для создания символической ссылки, очень похож на своего двоюродного брата для определения жесткой ссылки. Но он создает уже новый файл, содержащий указатель на старый файл (косвенный адрес).

Ошибки при создании символических ссылок В случае ошибки symlink() возвращает 1 и присваивает переменной Ошибки при создании символических ссылок В случае ошибки symlink() возвращает 1 и присваивает переменной errno одно из следующих значений: • EACCESS – у вызывающего процесса отсутствует разрешение на поиск для компонента пути oldpath или у вызывающего процесса нет разрешения на запись в каталог, содержащий newpath. • EEXIST – файл newpath уже существует — системный вызов symlink() не переписывает существующую запись каталога. • EFAULT – параметр oldpath или newpath содержит недопустимый указатель. • EIO – произошла внутренняя ошибка ввода вывода. • ELOOP – при разрешении пути oldpath или newpath встретилось слишком много символических ссылок. • EMLINK – в структуре inode, на которую указывает oldpath, уже достигнуто максимальное число указывающих на нее ссылок. • ENAMETOOLONG – слишком длинное значение oldpath или newpath. • ENOENT – компонент пути oldpath или newpath не существует. • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOSPC – на устройстве, которому принадлежит newpath, недостаточно места для создания новой записи каталога. • ENOTDIR – компонент пути oldpath или newpath не является каталогом. • EPERM – файловая система, которой принадлежит newpath, не допускает создания но вых символических ссылок. • EROFS – путь newpath принадлежит файловой системе, доступной только для чтения.

Удаление ссылки (или имени файла) • #include <unistd. h> • int unlink(const char *pathname); Удаление ссылки (или имени файла) • #include • int unlink(const char *pathname); Этот системный вызов удаляет имя файла. При этом анализируется число жестких ссылок, которые имеются у файла, и если это была последней ссылкой на файл, то файл удаляется сам. Если при этом удаляется последняя ссылка, с которой работают, то удаление произойдет только после завершения работы. Если же это символическая ссылка, то удаляется только ссылка, а файл не разрушается. Системный вызов unlink() не поддерживает удаление каталогов. Для этого в приложениях следует использовать вызов rmdir().

Ошибки при удалении ссылок В случае ошибки вызов возвращает 1 и присваивает переменной errno Ошибки при удалении ссылок В случае ошибки вызов возвращает 1 и присваивает переменной errno одно из следующих значений: • EACCESS – у вызывающего процесса нет разрешения на запись в родительский каталог файла pathname или у вызывающего процесса нет разрешения на поиск для компонента пути pathname. • EFAULT – параметр pathname содержит недопустимый указатель. • ЕIO – произошла ошибка ввода вывода. • EISDIR – путь pathname ссылается на каталог. • ELOOP – при прохождении pathname встретилось слишком много символических ссы лок. • ENAMETOOLONG – слишком длинное значение pathname. • ENOENT – компонент пути pathname не существует. • ENOMEM – недостаточно памяти для выполнения данного запроса. • ENOTDIR – компонент пути pathname не является каталогом. • EPERM – система не позволяет отсоединять файлы. • EROFS – путь pathname принадлежит файловой системе, доступной только для чтения.

Универсальное удаление • #include <stdio. h> • int remove(const char *path); Успешный вызов remove() Универсальное удаление • #include • int remove(const char *path); Успешный вызов remove() удаляет файл path из файловой системы и воз вращает значение 0. Если path — это файл, то remove() вызывает unlink(); если path — это каталог, то remove() вызывает rmdir(). В случае ошибки remove() возвращает 1 и присваивает переменной errno один из допустимых кодов ошибки, определенных для unlink() и rmdir() соот ветственно.

Переименование файла • #include <stdio. h> • int rename(const char *oldpath, const char *newpath); Переименование файла • #include • int rename(const char *oldpath, const char *newpath); В этом случае вместо существующего ранее файла создается новое имя файла, ничего другого не меняется. Но POSIX стандартизировал его и для файлов и, и для каталогов. Следует помнить, что при переименовании файла те изменения, которые были произведены в файле, отображаются во всех файлах, а при копировании, если это было сделано так: открыты два файла, скопирована информация из одного файла и перенесена во второй, закрыты эти файлы, изменения отображаются только в данном файле.

Ошибки при переименовании файлов В случае успеха системный вызов rename() возвращает значение 0, а Ошибки при переименовании файлов В случае успеха системный вызов rename() возвращает значение 0, а к фай лу, на который раньше указывал путь oldpath, после этого можно обращаться только при помощи пути newpath. В случае ошибки вызов возвращает 1, не меняет oldpath и newpath и присваивает переменной errno одно из следующих значений: • EACCESS – у вызывающего процесса нет разрешения на запись в родительский каталог файла oldpath или newpath, разрешения на поиск для компонента пути oldpath или newpath или разрешения на запись для oldpath, если oldpath — это каталог. Последний случай может быть проблемой, так как вызову rename() приходится обновлять каталог, когда oldpath является каталогом. • EBUSY – oldpath или newpath — это точка монтирования. • EFAULT – параметр cldpath или newpath содержит недопустимый указатель. • EINVAL – путь newpath является составляющей oldpath и, таким образом, переименование одного в другой сделает oldpath подкаталогом самого себя. • EISDIR – путь newpath существует и является каталогом, но oldpath — не каталог. • ELOOP – при разрешении пути oldpath или newpath встретилось слишком много сим волических ссылок. • EMLINK – на oldpath уже указывает максимальное число ссылок, или oldpath — это каталог, а на newpath уже указывает максимальное число ссылок. • ENAMETOOLONG – слишком длинное значение oldpath или newpath. • ENOENT – компонент oldpath или newpath не существует или является повисшей симво лической ссылкой. • ENOMEM – недостаточно памяти ядра для выполнения данного запроса. • ENOSPC – недостаточно пространства на устройстве для выполнения данного запроса. • ENOTDIR – компонент (за исключением потенциально последнего компонента) oldpath или newpath не является каталогом или oldpath — это каталог, a newpath существует и не является каталогом. • ENOTEMPTY – newpath — это каталог и он не пуст. • EPERM – по крайней мере, один из указанных в аргументах путей существует, для ро дительского каталога установлен бит закрепления в памяти, действительный идентификатор пользователя вызывающего процесса не совпадает ни с идентификатором пользователя файла, ни с идентификатором пользователя его предка, и процесс не привилегированный. • EROFS – файловая система помечена как доступная только для чтения. • EXDEV – oldpath и newpath принадлежат разным файловым системам.

Файловая система ОС UNIX • Файловая система – это способ организовывать расположение данных на Файловая система ОС UNIX • Файловая система – это способ организовывать расположение данных на носителе информации. Файлы расположены в каталогах. Каталоги – это древовидная система, которая представляет файловую систему в целом, но на отдельных носителях своя файловая система.

Структура файловой системы UNIX • Том файловой системы – данные, которые располагаются на выделенном Структура файловой системы UNIX • Том файловой системы – данные, которые располагаются на выделенном носителе информации и эти тома могут монтироваться или демонтироваться в единую файловую систему. Если рассматривать структурно файловую систему, то она выглядит примерно следующим образом: Загрузочный блок Суперблок Блок индексного дескриптора inode Информационный блок

Загрузочный блок • Загрузочный блок используется для расположения стандартной информации ОС и имеет нулевой Загрузочный блок • Загрузочный блок используется для расположения стандартной информации ОС и имеет нулевой логический номер. Физически он не обязан располагаться на нулевом номере, но с точки зрения логики – ноль. Это аппаратно зависимая часть ОС и информация, которая записана в нем, тоже аппаратно зависима.

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

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

Информационные блоки • Информационные блоки, в них располагаются файлы (данные файлов). Имеется отдельное место, Информационные блоки • Информационные блоки, в них располагаются файлы (данные файлов). Имеется отдельное место, где храниться информация, что занято, что свободно.

Типы файловой системы • s 5 fs. В такой файловой системе длина имен файлов Типы файловой системы • s 5 fs. В такой файловой системе длина имен файлов занимает 14 байт, имеется ограничение на количество файлов. Она считается не надежной, т. к. в ней только одна копия суперблока; • ffs. Считается быстрой файловой системой, т. к. в нем осуществляется быстрый доступ к данным. В отличие от файловой системы s 5 fs, в ffs храниться несколько копий данных; • Также имеется ext – семейство файловых систем (ext 2 или ext 3, где ext 3 – это журнальный вариант ext 2). В данной теме как раз и будет рассмотрена вайловая система ext 2.

Организация файловой системы ext 2 • В этой файловой системе разбивается на группы блоков: Организация файловой системы ext 2 • В этой файловой системе разбивается на группы блоков:

Структура блока в файловой системе ext 2 Под понятием суперблок понимается и копия суперблока Структура блока в файловой системе ext 2 Под понятием суперблок понимается и копия суперблока (а в нулевой группе блоков содержится основной суперблок). • ТДГ – таблица дескрипторов групп. • БКЗБ – битовая карта занятости блоков. • БКЗ inode – битовая карта занятости inod Таблица inode – таблица индексных дескрипторов (информационных ухлов). • ДГ – дескриптор группы. Он определяет распространение служебной информации, т. е. для своей группы. • АБКБ – адрес битов карты блоков. • АБК inode – адрес битов карты inode. • АТ – адрес таблицы inode.

Таблица индексных дескрипторов • В таблице индексных дескрипторов распространяются сами индексные дескрипторы (при чем Таблица индексных дескрипторов • В таблице индексных дескрипторов распространяются сами индексные дескрипторы (при чем используется сквозная нумерация), т. е. если в таблице inode группы блоков 0 последний индексный дескриптор был In. X, то в таблице inode группы блоков 1 дескрипторы будут начинаться с In(X+1), In(X+2) и т. д.

Представления индексных дескрипторов • IB – Indirect Block (КС –косвенная ссылка) • DIB – Представления индексных дескрипторов • IB – Indirect Block (КС –косвенная ссылка) • DIB – Double IB (ДКС – двойная КС) • TIB – Triple IB (ТКС – тройная КС)

Разбиение диска Все раздела диска разбивается на блоки фиксированного размера, кратного размеру диска (1024, Разбиение диска Все раздела диска разбивается на блоки фиксированного размера, кратного размеру диска (1024, 2048, 4096). Размер блока указывается при создании файловой системы на разделе жесткого диска. Для уменьшения фрагментации и количества перемещения головок жесткого диска, при чтении большого массива информации блоки объединяются в группы.

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

Суперблок – основной элемент файловой системы. Он содержит следующую информацию: • общее число блоков Суперблок – основной элемент файловой системы. Он содержит следующую информацию: • общее число блоков и информационных узлов в файловой системе • число свободных блоков и информационных узлов в файловой системе • размер блока файловой системы • количество блоков и информационных узлов в группе • размер информационных узлов (inode) • идентификатор файловой системы • номер первого блока данных (фактический номер блока, где располагается суперблок) Ø если размер блока равен 1024 байта, то номер первого блока равен 1; Ø если размер блока больше 1024 байт, то номер первого блока – 0. Ø это следует из того, что первые 1024 байта резервные для загрузчика ОС, а главная копия суперблока располагается со смещением 1024 байта. Ранние версии системы ext создавались копии суперблока в начале каждой группы блоков. В более современных системах они хранятся в 0, 1, 3, 5, 7, … группах.

Дескриптор группы • Каждая группа содержит информацию о занятости блоков и inode в виде Дескриптор группы • Каждая группа содержит информацию о занятости блоков и inode в виде битовой карты. Битовая карта занятости блоков обычно располагается в первом блоке группы. Если группа содержит копию суперблока, битовая карта располагается во втором блоке группы. Размер битовой карты равен одному блоку. Каждый бит карты обозначает состояние блока. Если 1 – блок занят, 0 – свободен. • Дескриптор группы – это структура, которая сожержит информацию об адресах битовой карты занятости блоков, битовой карты inode, таблицы inode соответствующей группы. Все дескрипторы групп содержаться в таблице дескрипторов групп, которая хранится в группе блоков 0. Для этой таблицы также создаются резервные копии. Информация, которая создается в дескрипторах групп, служит для доступа к файлу. • К примеру: задано имя файла, чтобы получить доступ к информации, изначально определяется номер индексного дескриптора. Следующим шагом определяется группа, по номеру группы выбирается номер индексного дескриптора, далее выделяется адрес данного файла. Только после этого возможен доступ к информации, содержащейся в данном файле.

Файлы устройств – это специальные файлы, имена их находятся в файловой системе, т. е. Файлы устройств – это специальные файлы, имена их находятся в файловой системе, т. е. имеется каталог, а в нем записи. Примеры таких файлов: • /dev/tty 00 • /dev/lp • /dev/discs • /dev/scsi • /dev/null – пустое устройство • /dev/zero – нулевое устройство • /dev/full – полное устройство

Обращение к устройству • Эти записи определяют устройства, но соответствующее inode для устройства по Обращение к устройству • Эти записи определяют устройства, но соответствующее inode для устройства по сути представляют точку входа в драйвер этого устройства, и когда через этот информационный узел выполняется какое либо действие, то ОС запускает на выполнение соответствующую функцию драйвера. • Файлы разделяются на блочные устройства и на символьные устройства. Файловые системы могут находиться только на блочном устройстве. Блочные устройства могут иметь связанные с ними символьные устройства для обеспечения быстрого и прямого доступа.

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

Последовательность действий по передаче 1) системный вызов чтения/записи (read/write) обращается к индексному дескриптору файла Последовательность действий по передаче 1) системный вызов чтения/записи (read/write) обращается к индексному дескриптору файла обычным образом; 2) ОС проверяет соответствующее поле в индексном дескрипторе и определяет является ли устройство блочным или символьным и извлекает старший номер устройства; 3) старший номер используется для индексации соответствующей таблицы устройств и нахождения процедуры драйвера устройства, нужной для непосредственного выполнения передачи данных.

Пример • В inode хранится и младший номер устройства, который позволяет уточнить доступ к Пример • В inode хранится и младший номер устройства, который позволяет уточнить доступ к конкретному устройству, если используется один драйвер для работы с несколькими устройствами (при использовании одного порта). • #include • int main() • { • int i, fd; • fd=open(“/dev/tty 00”, O_WRONLY); • for (i=0; i<100; i++) • write(fd, ’x’, 1); • close(fd); }

THE END THE END