Билет 09 - honeycarbs/bmstu-os-6sem GitHub Wiki
Файловая система: процесс и файловые структуры связанные с процессом. Файлы и открытые файлы, связь структур, представляющих открытые файлы на разных уровнях. Системный вызов open() и библиотечная функция fopen(): параметры и флаги, определенные на функции open(). Реализация системного вызова open() в ядре Linux. Пример: файл открывается два раза системным вызовом open() для записи и в него последовательно записывается строка «аааааааааааа» по первому дескриптору и затем строка «вввв» по второму дескриптору, затем файл закрывается два раза. Показать, что будет записано в файл и пояснить результат.
Процесс - это программа в стадии выполнения.
Процесс является единицей декомпозиции системы, именно ему выделяются ресурсы системы.
struct file - структура, которая позволяет организовывать работу с файлом, определяет системные таблицы всех открытых файлов.
struct file
{
...
struct path f_path;
struct inode *f_inode;
const struct file_operations *f_op;
spinlock_t f_lock;
...
atomic_long_t f_count;
unsigned int f_flags;
fmode_t f_mode; // режим доступа к файлу
long offset type;
struct mutex f_pos_lock;
loff_t f_pos; // смещение в файле
struct fown_struct f_owner;
...
};Каждый процесс также связан со структурами:
task_struct описывает запущенный в системе процесс, создаётся динамически, кроме процесса init. Для процесса init создаётся структура init_task.
struct task_struct { volatile long state; void *state; unsigned int flags; int prio, static_prio; struct list_head tasks; ... struct thread_struct thread; struct files_struct *files; ... };
struct files_struct *files формирует таблицу открытых файлов процесса. Каждый процесс имеет собственную такую таблицу. struct files_struct { atomic_t count; // счётчик пользователей структуры spinlock_t file_lock; // средство взаимоисключения int max_fds; // максимальное количество файловых дескрипторов ... struct file **fd; // массив всех файловых дескрипторов ... struct file *fd_array[32]; // массив открытых файловых дескрипторов };
struct fs_struct *fs описывает файловую систему, к которой относится процесс. До запуска программы является исполняемым файлом.
struct fs_struct
{
atomic_t count; // количество пользователей
rwlock_t lock;
int umask; // права доступа
struct dentry *root; // корневая директория
struct dentry *pwd; // текущая директория
struct dentry *altroot; // альтернативная корневая директория
struct vfsmount *rootmnt; // объект монтирования корневой директории
struct vfsmount *pwdmnt; // объект монтирования текущей директории
struct vfsmount *altrootmnt; // объект монтирования альтернативной корневой директории
};namespace позволяет каждому процессу иметь своё видение смонтированной файловой системы
struct namespace
{
atomic_t count;
struct vfsmount *root;
struct list_head list;
struct rw_semaphore sem;
};Обычные файлы расположены во вторичной памяти, на устройстве долговременного хранения, такие файлы называются регулярными.

Для процесса открытия файла в различных структурах, даже в структурах ядра, имеется функция open. Системный вызов open возвращает файловый дескриптор.
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Используемые флаги:
O_RDONLY - только чтение
O_WRONLY - только запись
O_RDWR - доступ на чтение и на записьНекоторые флаги создания файлов и флаги состояния файлов:
O_APPEND - файл открывается в режиме добавления
O_CLOEXEC - устанавливает флаг close-on-exec на новом файловом дескрипторе
O_CREAT - файл будет создан, если он ещё не существует
O_PATH - создаётся файловый дескриптор для указания положения в дереве файловой системы и для выполенния операций, работающих исключительно на уровне файловых дескрипторов
O_TMPFILE - создаётся безымянный временный файл
fopen() - это функция стандартной библиотеки. Стоит отметить, что стандартный ввод-вывод буферизуется. Также работает с форматированными данными.
FILE *fopen(const char *fname, const char *mode);
``
Системный вызов open:
```C
int open(const char *filename, int access, unsigned mode)Системный вызов open() создаёт новый файловый дескриптор для открытого файла, запись в общесистемной таблице открытых файлов. Эта запись регистрирует смещение в файле и флаги состояния файла.
Системный вызов open() является обёрткой функции ядра ksys_open(), которая вызывает функцию do_sys_open(): в теле функции do_sys_open() вызывается функция build_open_how() и функция do_sys_openat2(). Функция do_sys_openat2() вызывается функции build_open_flags(), getname(filename), get_unused_fd_flags() и, если функция get_unused_fd_flags() возвращает fd > 0, то вызывается функция do_filp_open(). Функция do_sys_openat2() выполняет все задачи системного вызова open. Сначала выполняется проверка правильности флагов и их преобразование во внутреннее представление функцией build_open_flags(). В случае неуспешного преобразования и проверки будет возвращена ошибка.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int fd1 = open("file.txt", O_RDWR);
int fd2 = open("file.txt", O_RDWR);
char buf1[] = "aaaaaaaaaaaa";
char buf2[] = "bbbb";
write(fd1, buf1, sizeof(buf1) - 1);
write(fd2, buf2, sizeof(buf2) - 1);
close(fd1);
close(fd2);
return 0;
}Результатом работы программы будет: "bbbbaaaaaaaa"
Файл дважды открывается для записи с помощью open(), при этом создается два экземпляра структуры struct file, которые описываются один статический файл. Файловые дескрипторы независимы между собой, поэтому положение указателей f_pos будут изменяться независимо друг от друга.