Билет 16 - honeycarbs/bmstu-os-6sem GitHub Wiki

Открытые файлы: системный вызов open(): int open(const char* pathname, int flags); int open(const char* pathname, int flags, mode_t mode); пояснить смысл параметров. Основные флаги. Флаг CREATE. Реализация системного вызова open() в системе – действия в ядре: SYSCALL_DEFINE3(open,…) -> ksys_open(filename, flags, mode) -> do_sys_open() -> do_sys_openat2() … найти наименьший файловый дескриптор... Действия, если флаг O_CREATE установлен?

Открытые файлы: системный вызов open()

Системный вызов open() создаёт новый файловый дескриптор для открытого файла, запись в общесистемной таблице открытых файлов. Эта запись регистрирует смещение в файле и флаги состояния файла.

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

Функция ореn() открывает файл, расположенный по пути pathname, и устанавливает режим доступа к нему в соответствии со значением аргумента flags. Аргумент flags представляет собой комбинацию основного режима доступа и модификаторов.

Аргумент mode требуется только при использовании модификатора O_CREAT. В этом случае mode может принимать одно из трех значений:

S_IWRITE - Доступ по записи
S_IREAD -	Доступ по чтению
S_IWRITE | S_IREAD - Доступ по чтению/записи

Возвращаемое значение - дескриптор файла.

Основные флаги.

Используемые флаги:

O_RDONLY - только чтение
O_WRONLY - только запись
O_RDWR - доступ на чтение и на запись

Некоторые флаги создания файлов и флаги состояния файлов:

O_APPEND - файл открывается в режиме добавления
O_CLOEXEC - устанавливает флаг close-on-exec на новом файловом дескрипторе
O_CREAT - файл будет создан, если он ещё не существует
O_EXCL - флаг, который при использовании с O_CREAT, при наличии уже созданного файла завершит вызов возвратом ошибки. Позволяет реализовывать поведение "Файл существует, заменить?"
O_PATH - создаётся файловый дескриптор для указания положения в дереве файловой системы и для выполенния операций, работающих исключительно на уровне файловых дескрипторов
O_TMPFILE - создаётся безымянный временный файл
FILE *fopen(const char *fname, const char *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(). В случае неуспешного преобразования и проверки будет возвращена ошибка.

Нахождение наименьшего файлового дескриптора происходит в функции get_unused_fd_flags, вызов которой происходит после вызова getname. В get_unused_fd_flags происходит два последовательных вызова: __get_unused_fd_flags и alloc_fd.

Функция alloc_fd отвечает за поиск свободного файлового дескриптора. В случае успеха (то есть дескриптор обнаружен) вызывается функция __set_open_fd (то есть функция, которая помечает дескриптор занятым).

Функция path_openat() вызывается из функции do_filp_open(), вызов которой, в свою очередь, как указывалось выше, расположен в функции do_sys_opent2().

В функции open_last_lookups() (вызывается из функции path_openat() в случае, если флаги O_TMPFILE и O_PATH не установлены) первоначально проверяется, установлен ли флаг O_CREAT.

После описанных действий вызвается функция нахождения или создания файла (lookup_open()).

По завершению вновь проверяется, естановлен ли флаг O_CREAT. В том случае, если флаг установлен, вызывается функция fsnotify_create(), которая уведомляет файловую систему о создании файла.

Затем вызывает функция inode_unlock(), которая снимает установленную блокировку. В ином случае, если флаг O_CREAT не установлен, вызывается функция inode_unlock_shared(), которая также снимает установленную блокировку.

В дальнейшем, если требуется, выполняется переход по символьной ссылке с использованием функции step_into().

Действия, если флаг O_CREATE установлен

В том случае, если флаг установлен, вызывается функция inode_lock(), которая блокирует inode файла директории на запись с использованием семафора. В ином случае вызывается функция inode_lock_shared(), которая блокирует inode файла директории на чтение с использованием семафора.

/*
 * lock for writing
 */
void __sched down_write(struct rw_semaphore *sem)
{
	might_sleep();
	rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_); // <- семафор
	LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
}
EXPORT_SYMBOL(down_write);