Билет 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);