Внутреннее устройство ядра Linux 2.4

Управление файловыми дескрипторами


В Linux между пользовательским файловым дескриптором и структурой inode в ядре, существует несколько уровней косвенных ссылок. Когда процесс открывает файл системным вызовом open(2), ядро возвращает положительное малое целое число, которое затем используется в операциях ввода/вывода над заданным файлом. Это целое число является индексом в массиве указателей на struct file. Каждая struct file содержит указатель на dentry file->f_dentry. Каждая dentry имеет указатель на inode dentry->d_inode.

Каждая задача содержит поле tsk->files которое указывает на struct files_struct, определенную в include/linux/sched.h:

/* * Структура таблицы открытых файлов */ struct files_struct { atomic_t count; rwlock_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]; };

Поле file->count - это счетчик ссылок, увеличивается в get_file() (обычно вызывается из fget()) и уменьшается в fput() и в put_filp().Различие между fput() и put_filp() состоит в том, что fput()

выполняет больший объем работы, необходимый для регулярных файлов, т.е. освобождение блокировок, освобождение dentry и пр., в то время как put_filp() работает только с таблицей файловых структур, т.е. уменьшает счетчик, удаляет файл из anon_list и добавляет его в free_list, под блокировкой files_lock.

Таблица tsk->files может использоваться совместно родителем и потомком, если потомок был создан системным вызовом clone() с флагом CLONE_FILES. В качестве примера можно привести kernel/fork.c:copy_files() (вызывается из do_fork()), где только лишь увеличивается счетчик ссылок file->count. вместо обычного (для классического fork(2) в UNIX) копирования таблицы дескрипторов.

При открытии файла в памяти размещается новая файловая структура, которая устанавливается в слот current->files->fd[fd] и взводится бит fd в current->files->open_fds. Действия эти выполняются под защитой от записи read-write блокировкой current->files->file_lock. При закрытии дескриптора сбрасывается бит fd в current->files->open_fds, а поле current->files->next_fd устанавливается равным fd на случай поиска первого неиспользуемого дескриптора при следующем открытии файла.



Содержание раздела