- •Лекция 1. 7.02.2014
- •Монтирование файловой системы.
- •Лекция 2. 10.02.2014
- •Лекция 3. 17.02.2014
- •Открытые файлы.
- •Лекция 4. 24.02.2014
- •Лекция 5. 3.03.2014 Файлы.
- •Регистрация и дерегистрация фс
- •Лекция 6. 17.03.2014
- •Организация виртуальной файловой системы (vfs)
- •Функции для работы с элементами фс proc.
- •Лекция 7. 24.03.2014
- •Файловая система specfs.
- •Терминалы.
- •Терминальный ввод-вывод.
- •Лекция 8. 31.03.2014
- •Типы флагов структуры termios.
- •Принятые соглашения и стандарты.
- •Простые способы открытия псевдотерминалов.
- •Лекция 9. 7.04.2014
- •Лекция 10. 14.04.2014
- •Реализация доступа к устройствам.
- •Структура контроллера внешнего устройства.
- •Южный и северный мосты.
- •Последовательные и параллельные интерфейсы.
- •Лекция 11. 21.04.2014
- •Управление вводом-выводом.
- •Прерывания.
- •Лекция 12. 28.04.2014 Контроллер прерывания.
- •Лекции 13-14. 5.05.2014, 12.05.2014
- •Проблемы прямого доступа к памяти.
- •Управление устройствами.
- •Многослойная модель системы ввода-вывода.
- •Пространство имен устройств.
- •Доступ к драйверу символьного устройства.
- •Доступ к драйверу блочного устройства.
- •Дополнительная информация о драйверах.
- •Лекция 15. 19.05.2014
- •Типичные точки входа в драйвер устройства.
- •Файлы устройств.
- •Буферизация ввода-вывода.
- •Схемы обменной буферизации
- •Обслуживание прерываний.
- •Лекция 16. 26.05.14
- •Лекция 17. 02.06.14
Лекция 5. 3.03.2014 Файлы.
Для того, чтобы система могла работать с файлами, вводится абстракция «открытый файл».
В системе для работы с файлами создаются дополнительные структуры.
Только процессы могут выполнять функции read/write. Процесс, заинтересованный в работе с файлом, открывает файл. При каждом открытии файла каким-либо процессом ядро создает в системной области памяти экземпляр структуры файл (struct file).
Каждый файл имеет единственный vnode, inode и все процессы, открывшие данный файл получат указатель на одни и те же vnode inode. Struct file представляет из себя двусвязный список.
struct file |
{ |
mode_t f_mode; |
loff_t f_pos; |
unsigned short f_flags; |
unsigned short f_count; |
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; |
struct file *f_next, *f_prev; |
int f_oner; |
struct inode *f_inode; |
struct file_operations *f_op; |
unsigned long f_version; |
void *orivate_data; |
}; |
Функции, которые система предоставляет для работы с файлом на самом деле являются методами этой структуры.
В зависимости от конкретной файловой системы struct operation может иметь уникальную реализацию или использовать некоторый универсальный метод, если такой имеется. Если вместо метода/ссылки на метод указывается null, значит данная операция в конкретной файловой системе не определена. С процессом ассоциированы три структуры. Три структуры данных связывают вместе файловую систему (ВФС) и процессы. Это
Struct:
files_struct
fs_struct
namespace
Files_struct определена в linux/file.h
<linux/file.h>
struct files_struct
{
atomic_t count; //счетчик ссылок. изменение – неделимая операция
spinlock_t file_lock; // защита структуры
int max_fds; // максимальное количество файловых объектов
int max_fdset; // максимальное количество файловых дескрипторов
int next_fd; // номер следующего файлового дескриптора
struct file **fd; // массив всех файловых объектов
fd_set *close_on_exec; // файловые дескрипторы для закрытия или исполнения
fd_set *open_fds;
fd_set close_on_exec_init;
fd_set open_fds_init; // инициализированный набор файловых дескрипторов
struct file *fd_array[NR_OPEN_DEFAULT]; //список открытых файловых объектов. Константа // определена в системе и по умолчанию равна 32 (можно открыть не более 32 файловых //объектов). При превышении система создаст новый массив.
};
<linux/fs_struct.h>
struct fs_struct
{
atomic_t count; // количество использованных юзером структур
rwlock_t lock; // read-write lock
int umask;
struct dentry *root; // корневая директория
struct dentry *pwd; // dentry of current working directory. Избавляет от необходимости указывать полное имя файла
struct dentry *altroot; // dentry of alternative root
struct vfsmount *rootmnt;
struct vfsmount *pwdmnt;
struct vfsmount *altrootmnt;
};
Spinlock – блокировка, которая осуществляется путем активного ожидания на процессе. read_writelock – блокировка более высокого уровня в ядре.
Перечисленные структуры относятся к процессу. Fs_struct содержит информацию о файловой системе, которая связана с процессом. Процесс в Линукс может быть связан с разными файловыми системами.
Третья структура – namespace. Была добавлена в ядро линукс начиная с версии 2.4. Она позволяет каждому процессу иметь уникальный взгляд на подмонтированные файловые системы. Структура имеет следующий вид.
<linux/namespace.h>
struct namespace
{
atomic_t count;
struct vfsmount *root;
struct list_head list; // list of mount points. Точно определяет двусвязный список //подмонтированных файловых систем, которые составляют namespace
struct rw_semaphore sem; // sem protecting the namespace
};
Данная структура линкуется дескриптору каждого процесса. Для большинства процессов имеются уникальные структуры files_struct и fs_struct (каждый процесс ссылается на свои собственные files_struct и fs_struct). Но могут быть установлены флаги CLONE_FILES и CLONE_FS, тогда указанные структуры будут разделяемыми, то есть несколько процессов будут ссылаться на одни и те же структуры. Соответственно count в каждой структуре будет равен количеству ссылок. Потоки (threads) обычно определяют эти две константы и таким образом разделяют единственную files_struct и fs_struct процессам. Как правило, обычный процесс указанные флаги не устанавливает и, таким образом, имеет собственную системную информацию об открытых файлах. Структура namespace работает по-другому. Все процессы разделяют одно и то же пространство имен (namespace), то есть они все видят одну и ту же иерархию файлов, используя одну и ту же таблицу монтирования. Однако, если установлен флаг CLONE_NEWNS, с использованием системного вызова clone() процессу выделяется уникальная структура namespace. В силу того, что большинство процессов не устанавливают этот флаг, все процессы наследуют пространство имен своих предков.
Read-write.
ssize_t read(struct file *filp, char *buff, size_t count, loff_t *offp);
ssize_t write(struct file *filp, char *buff, size_t count, loff_t *offp);
Параметры одинаковы, потому что, с точки зрения системы, read и write фактически выполняют одинаковые действия.
Read-write являются методами структуры struct operations.
Первый параметр – указатель на файл, count – размер требуемых для передачи данных, *buff – указатель на user buffer. В этот буфер данные или записываются или это пустой буфер при чтении,
*offp – указатель (loff_t – long offset type), указывает смещение в файле.
Адреса пространства пользователя не могут напрямую быть использованы для выполнения копирования (memory copy). Адреса пространства пользователя не могут быть напрямую использованы в пространстве ядра. На это есть несколько причин. Первое и важнейшее отличие адресного пространства ядра от адресного пространства процесса (юзера) заключается в том, что адресное пространство юзера выгружаемо (swapped). Когда ядро обращается, используя указатель на юзерспейс, связанный с какой-то страницей, эта страница может отсутствовать в памяти и возникнет исключение. Важно отметить, что в линукс 2.0 для архитектуры х86 используются совершенно разные карты памяти для userspace и kernelspace. Отсюда указатели на адресное пространство юзера не могут быть выделены в пространстве ядра. Для того, чтобы избежать этих проблем, необходимо копировать фактический сегмент данных процесса в пространство ядра – так называемое кросспространственное (cross-space) копирование. Для этого в линукс имеются специальные функции, которые определены в файле <asm/uaccess.h>. Эти функции оптимизируют процесс копирования.
<asm/uaccess.h>
unsigned long copy_to_user(void *to, const void *from, unsigned long count);
unsigned long copy_from_user(void *to, const void *from, unsigned long count);
Системные вызовы read-write переводят систему в режим ядра и уже в режиме ядра выполняются действия с драйверами устройства. Но в это время супервизор не может работать с адресным пространство процесса, так как пространство может быть выгружено (и будет, если процесс спит более 20 секунд).
Read-write вызывают другие функции, в том числе copy_to_user, copy_from_user.
ssize_t dev_read(struct file *file, char *leaf, size_t count, loff_t *ppos);
Схема 2.
Ошибки специфицированы в <linux.errno.h>
