Жёсткие и символические ссылки¶
Жёсткая ссылка¶
Жёсткая ссылка (hard link) — это дополнительная запись в директории, указывающая на уже существующий inode. Все имена,
которые ссылаются на один inode, абсолютно равноправны. Счётчик st_nlink в inode хранит общее количество жёстких
ссылок.
Ограничения жёстких ссылок:
- нельзя создавать на директории (кроме служебных
.и..); - нельзя создавать между разными файловыми системами (inode уникален только в пределах одной ФС).
Создание в shell:
Пример: если создать жёсткую ссылку и затем удалить исходное имя, данные останутся доступны:
Символическая ссылка¶
Символическая ссылка (symlink) — отдельный объект файловой системы с собственным inode типа l. В данных этого inode
хранится строка-путь до целевого файла. При открытии симлинка ядро разыменовывает путь и продолжает обработку с реальным
файлом.
Создание в shell:
Преимущества перед жёсткими ссылками:
- можно создавать между разными файловыми системами;
- можно ссылаться на директории;
- можно ссылаться на несуществующие файлы (broken symlink — «битая» ссылка).
Недостатки:
- разыменование требует дополнительного обращения к диску;
- удаление целевого файла делает симлинк битым.
Сравнение¶
Жёсткая ссылка (hard link) Символическая ссылка (symlink)
директория /home/user/ директория /home/user/
┌───────────────────────────┐ ┌───────────────────────────┐
│ "file.txt" ──▶ inode 42 │ │ "file.txt" ──▶ inode 42 │
│ "link.txt" ──▶ inode 42 │ │ "link.txt" ──▶ inode 99 │
└───────────────────────────┘ └───────────────────────────┘
│ │ │ │
└────────────┘ │ │
│ ▼ ▼
▼ ┌──────────────┐ ┌──────────────┐
┌──────────────────┐ │ inode 99 │ │ inode 42 │
│ inode 42 │ │ type: l │ │ type: - │
│ type: - │ │ nlink: 1 │ │ nlink: 1 │
│ nlink: 2 ←── │ два имени │ data: │ │ data: │
│ data: │ │ "/home/user/ │ │ (содержимое)│
│ (содержимое) │ │ file.txt" │ │ │
└──────────────────┘ └──────┬───────┘ └──────────────┘
│ ▲
│ разыменование │
└──────────────────┘
ядро читает путь из data inode 99
и открывает inode 42
rm file.txt: rm file.txt:
┌───────────────────────────┐ ┌───────────────────────────┐
│ "link.txt" ──▶ inode 42 │ │ "link.txt" ──▶ inode 99 │
└───────────────────────────┘ └───────────────────────────┘
nlink: 1, данные живы inode 99 data: "/home/user/file.txt"
→ ENOENT: битая ссылка
| Свойство | Жёсткая ссылка | Символическая ссылка |
|---|---|---|
Тип в ls -l |
- (как файл) |
l |
| Указывает на | inode | строку-путь |
| Между разными ФС | Нет | Да |
| На директории | Нет | Да |
| Выживает удаление оригинала | Да | Нет (битая ссылка) |
Увеличивает st_nlink |
Да | Нет |
Системные вызовы link и symlink¶
#include <unistd.h>
int link(const char *oldpath, const char *newpath); // жёсткая ссылка
int symlink(const char *target, const char *linkpath); // символическая ссылка
linkсоздаёт новую запись в директории, указывающую на тот же inode, что иoldpath;symlinkсоздаёт новый inode типаl, содержащий строкуtarget.
Прочитать цель символической ссылки (не разыменовывая её):
Реализация ln¶
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
int symbolic = 0;
int arg = 1;
if (argc >= 2 && strcmp(argv[1], "-s") == 0) {
symbolic = 1;
arg = 2;
}
if (argc - arg != 2) {
fprintf(stderr, "Usage: %s [-s] src dst\n", argv[0]);
return 1;
}
const char *src = argv[arg];
const char *dst = argv[arg + 1];
int res;
if (symbolic) {
res = symlink(src, dst);
} else {
res = link(src, dst);
}
if (res == -1) {
perror("link/symlink");
return 1;
}
return 0;
}
Варианты с дескриптором директории¶
Для использования в многопоточных программах и при работе с дескрипторами директорий существуют at-варианты:
#include <fcntl.h>
#include <unistd.h>
int linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags);
int symlinkat(const char *target, int newdirfd, const char *linkpath);
ssize_t readlinkat(int dirfd, const char *pathname,
char *buf, size_t bufsiz);
Если вместо дескриптора директории передать AT_FDCWD, функция работает относительно текущего рабочего каталога, как
обычный вариант.
Связанные темы¶
- Основы файловых систем — inode и механизм именования файлов
- Команды mv и rm —
unlink, счётчикst_nlink - Операции с директориями —
lstatдля проверки типа объекта - Права доступа и атрибуты файлов — права на симлинки
Источники¶
man 2 link— создание жёсткой ссылкиman 2 symlink— создание символической ссылкиman 2 readlink— чтение пути из символической ссылкиman 2 unlink— удаление записи из директорииman 2 linkat— вариант link с дескрипторами директорийman 1 ln— команда ln в оболочке