Файлы, каталоги и файловые дескрипторы

⏱ 30 мин · 🧩 заданий: 5

«Всё есть файл»

В Unix через файловый интерфейс (open, read, write, close) доступно почти всё:

Тип ls -l Пример
обычный файл - /etc/passwd
каталог d /home
символическая ссылка l /bin → usr/bin
блочное устройство b /dev/sda — диск
символьное устройство c /dev/tty, /dev/null
именованный канал p созданный mkfifo
сокет s /run/systemd/notify

Плюс псевдофайлы /proc и /sys.

Дерево каталогов

Все файловые системы собраны в одно дерево с корнем /. Каталог — особый файл, содержащий таблицу «имя → номер индексного дескриптора». Путь /home/anna/notes.txt разрешается по шагам: корень → запись home → запись anna → запись notes.txt.

Три уровня таблиц

Когда процесс открывает файл, ядро связывает три структуры:

процесс A ядро (общие для системы) таблица дескрипторов таблица открытых файлов индексные дескрипторы ┌────┬──────┐ ┌───────────────────────┐ (inode в памяти) │ 0 │ ────┼───────────────▶ │ tty: pos —, O_RDWR │────▶ inode /dev/pts/0 │ 1 │ ────┼───────────────▶ │ │ │ 3 │ ────┼───────────────▶ │ file1: pos=100,O_RDONLY│──┐ └────┴──────┘ │ │ ├─▶ inode 1234 процесс B (потомок A) │ file2: pos=0, O_WRONLY│──┘ (data.txt) ┌────┬──────┐ └───────────────────────┘ │ 3 │ ────┼──────────▶ (тот же file1, что у A — после fork) │ 4 │ ────┼──────────▶ file2 (B сам открыл data.txt ещё раз) └────┴──────┘
Уровень Где Что хранит
Таблица дескрипторов у каждого процесса номер → указатель на открытый файл, флаг FD_CLOEXEC
Таблица открытых файлов (struct file) общая в ядре текущая позиция, режим открытия, флаги, счётчик ссылок, операции
Индексный дескриптор (inode) общий, по одному на файл метаданные и расположение данных файла

Следствия:

  • fork и dup копируют дескриптор — позиция общая;
  • два open одного файла — две разные записи struct file, позиции независимы;
  • запись открытого файла освобождается, когда закрыты все ссылающиеся на неё дескрипторы (счётчик ссылок = 0).

dup и dup2

int copy = dup(fd);       /* наименьший свободный номер — копия fd */
dup2(fd, 1);              /* сделать 1 копией fd (1 закрывается, если был открыт) */

Так shell выполняет cmd > file:

pid_t pid = fork();
if (pid == 0) {
    int fd = open("file", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    dup2(fd, STDOUT_FILENO);
    close(fd);
    execvp("cmd", argv);
}

Права доступа

Каждый файл имеет владельца, группу и 9 бит прав: rwx для владельца, группы и остальных.

$ ls -l script.sh
-rwxr-x--- 1 anna dev 120 окт 25 10:00 script.sh
chmod 750 script.sh      # rwx r-x ---
Бит Для файла Для каталога
r читать содержимое читать список имён
w изменять содержимое создавать, удалять, переименовывать файлы в нём
x выполнять входить (проходить по пути)

Удаление файла — право записи в каталог, а не в сам файл.

Метаданные: stat

struct stat st;
stat("data.txt", &st);
printf("inode=%lu links=%lu size=%ld\n",
       (unsigned long)st.st_ino, (unsigned long)st.st_nlink, (long)st.st_size);
stat data.txt

Итог

  • В Unix «всё есть файл»: обычные файлы, каталоги, устройства, каналы, сокеты.
  • Три уровня: дескрипторы процесса → таблица открытых файлов (позиция) → inode (метаданные).
  • fork и dup разделяют позицию; open ещё раз — новая позиция.
  • open возвращает наименьший свободный номер; dup2 — перенаправления.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Заполнить таблицу

Что общее, а что своё после fork, если файл был открыт до него?

Свой у каждого процессаОбщий для родителя и потомка
Таблица файловых дескрипторов
Структура открытого файла (struct file)
Текущая позиция в файле (offset)
Флаги открытия (O_APPEND, O_NONBLOCK)
Флаг FD_CLOEXEC дескриптора
Отметьте ячейку — «+», пустая — «−».
Задание 2 Ввод ответа

Что окажется в файле out.txt?

int fd = open("out.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fork() == 0) { write(fd, "AB", 2); _exit(0); }
wait(NULL);
write(fd, "CD", 2);
Задание 3 Написать код

Перенаправьте стандартный вывод в файл: откройте "log.txt" на запись (создать, обрезать, права 0644) и сделайте дескриптор 1 его копией через dup2, затем закройте лишний дескриптор.

Задание 4 Ввод ответа

Какой наименьший номер дескриптора вернёт open у процесса, у которого открыты только 0, 1 и 2, а потом закрыт 0?

Задание 5 Заполнить таблицу

Какой тип файла показывает первый символ в ls -l?

обычный файлкаталогсимволическая ссылкаблочное устройствосимвольное устройствоканал FIFOсокет
-
d
l
b
c
p
s
Отметьте ячейку — «+», пустая — «−».

Войдите, чтобы отмечать пройденные уроки.