06 сем Семинар 6 ЛР 5 Open - chrislvt/OS GitHub Wiki
Лаба 5.
Возникает много проблем, если не учитывать что ввод вывод в файл с использованием библ. stdio буфферизуется.
1 Программа один раз вызов open. Процесс получается файловый дескриптор типа integer. Затем вызов fdopen ей передается полученный файловый дескриптор. В результате мы получаем указатель fs1. После setbuf. То есть мы открыли файл один раз, но потом получаем указатель на этот файл. Дальше в цикле вызов scanf, первый вызов scanf считывает в буфер 20 символов (первый буфер заполняется полностью), в файле символы англ алфавита. Второй вызов fdopen создает указатель fs2. Второй вызов scanf считывает оставшиеся символы из файла. В структуре FILE есть флаг заполнен буфер или нет. Несмотря на то что действия выполняются в цикле буфер заполнится один раз.
2 Программа. Два раза вызов open. Создается два дескриптора открытых файлов. Выполняется чтение из файла по каждому дескриптору и вывод на экран. Получается закономерный результат
3 Программа. Два раза вызов fopen. Файл открывает два раза, получаем два файловых дескриптора. Но файл открываем для записи. И в этот файл используя два разных дескриптора пишем, по одному четные символы по другому нечетные. Запись из буфера (fprintf буферизованный).
Информация записывается в файл из буфера:
- Буфер заполнен.
- Flush
- Fclose
Надо посмотреть что оказалось в файле.
Но задание расширяется.
Мы считываем не так как хотели бы, и можем потерять данные если не помним о буферизации. Все это заложены в идеи открытых файлов. В демоне отработали создание потока. Каждую программу в двух вариантах: как написано только убираем break?, и создаем поток, в главном open и в доп потоке open. В 3 программе также. Вся проблема в том что создается два дескриптора открытых файлов. Но сам файл физический один. Один inode!!
Когда мы говорим о файлах надо начинать со структуры task_struct. Поскольку открыть файл может только процесс. В структуре есть поля связанные с открытыми файлами.
struct task_struct
{
...
/* File system information */
struct fs_struct; // Почему процесс имеет указатель на структуру которой содержит информацию о фс. Потому что процесс не всю жизнь был процессом, до этого он был файл.
/* Open file information */
struct files_struct; // Описывает открытые файлы процесса. Каждый процесс имеет собственную таблицу открытых файлов. Эта таблица определяется данной структурой.
/* Namespaces */
struct nsproxy *nsproxy; // Она никак не участвует в нашей лр. Но информация о файлах хранится в трех структурах (выше и эта). Эта содержит перечень структур.
...
В современных ядрах имеется 7 типов namespace`ов. Основная задача максимально изолировать процесс от остальной части системы. В любой момент времени принадлежит любой процесс принадлежит ровно одному экземпляру namespace каждого типа. Для работы с файлами важнейшим является mnt_namespace.
struct nsproxy
{
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
}
Версия ядра 4.10
struct fs_struct
{
int users;
spinlock lock;
seqcount_t seq;
int umask;
int in_exec;
struct path root, pwd; //pwd текущий каталог фс, в который лежал запущенный на выполнение файл.
}
struct path
{
struct vfsmount *mnt;
struct dentry *dentry;
}
struct files_struct
{
atomic_t count;// счетчик использования структуры.
...
unsigned int next_fd; // число открытых процессом файлом.
unsigned long close_on_exec_init[1]; // число файлов которые должны быть закрыты exec-ом
unsigned long open_fds_init[1]; //число открытых файлов
...
struct file rcu *fd_array [NR_OPEN_DEFAULT]; // NR_OPEN_DEFAULT -максимальный размер. В элементе находится указатель на дескриптор открытого файла в таблице открытых файлов. Каждый файл таблицы файловый системы имеет дескриптор.
struct fdtable fdtab; // дескриптор открытого файла процесса. Но каждый процесс имеет собственную таблицу открытых файлов. Но в системе одна таблица открытых файлов и эта структура struct file.
...
}
struct file
{
...
union {
struct list_head fu_list;
...
} f_u;
struct path f_path;
struct inode *f_inode;
const struct file_operations *f_op;
// во всех структурах присутствуют средства взаимоисключения. Предлагает свои spinlock`и
spinlock_t f_lock;
...
atomic_long_t f_count; // atomic неделимо атомарно.
unsigned int f_flags;
fmode_t f_mode;
loff_t f_pos;
...
}
(на картинке ошибка, стрелка должна идти не из fd[2], а из fd[3]!!!
Для каждой из 3 программ это надо нарисовать.
Любая фс имеет такие функции для работы с файлами как fseek open read write release.
Информацию об открытых файлов можем получить с помощью stat_struct. В своих лр должны привести. Используя информацию вы должны в 3 программе, где должны выводить функцию с помощью stat. Выводим инфу сразу после того как файл открыли. Первый раз открыли выводите size inode, Второй раз открыли выводите. Закрыли fclose выводите. И после второго fclose выводим. В программе должна быть объявлена переменная struct stat sbuf;
stat("f.txt" &sbuf)
printf("inode %d, (int) inode sbuf.st_ino);
#include <fcntl.h>
int open(const char *pathname, int oflag, ...); // многоточие в ISO означает
fd=open("mt.txt", ORDWR|O_CREATE|O_EXCH, 0644);//первая константа правда доступа read write, вторая create, что если файл уже существует и задан флаг o_create возникнет ошибка. Контролирует удаление существующего файла. Такая комбинация флагов, а именно проверка выполняется атомарно.
//Возращает целое число, и воспринимается как идентификатор файл в процессе. Полученный дескриптор передается системным вызовам read write и др.
<stdin.h>
int fileno(FILE *fp); //получить файловый дескриптор в
//файловый дескриптор является объектом открытого процесса, который содержит указатель на объект открытого файла struct file и набора флагов
//каждый дескриптор открытого файл имеет независимую переменную f_pos, которая начинается от нулевого значения!!!!