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 буферизованный).

Информация записывается в файл из буфера:

  1. Буфер заполнен.
  2. Flush
  3. 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, которая начинается от нулевого значения!!!!
⚠️ **GitHub.com Fallback** ⚠️