Ответ
В Linux и других Unix-подобных системах файловая подсистема отделяет запись в каталоге (имя файла) от самих данных на диске (inode). Когда процесс открывает файл, ядро увеличивает счетчик ссылок для соответствующего inode.
Поведение:
- Процесс Б успешно выполняет системный вызов
unlink("file.txt"). - Имя файла (
file.txt) немедленно удаляется из каталога. Командаlsего больше не покажет. - Однако, если процесс А уже открыл этот файл (имеет открытый файловый дескриптор), данные на диске не уничтожаются. Inode и блоки данных остаются доступными для процесса А через его дескриптор.
- Файл будет окончательно удален с диска, только когда процесс А закроет файл (и счетчик ссылок на inode станет равен 0).
Пример на C++ (системные вызовы POSIX):
// Процесс А (читатель)
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
int main() {
int fd = open("testfile.txt", O_RDONLY);
if (fd == -1) { /* обработка ошибки */ }
char buffer[256];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
std::cout << "Прочитано: " << bytes_read << " байт. Файл открыт.n";
// В этот момент другой процесс может выполнить unlink("testfile.txt")
// Файл "исчез" из директории, но мы можем продолжать чтение.
lseek(fd, 0, SEEK_SET); // Вернуться к началу файла
bytes_read = read(fd, buffer, sizeof(buffer)); // Чтение все еще работает!
sleep(10); // Имитация долгой работы с файлом
close(fd); // ТЕПЕРЬ данные файла могут быть физически удалены с диска.
return 0;
}
Ключевой момент: Это поведение позволяет выполнять долгие операции (например, обработку логов) без риска, что другой процесс удалит рабочий файл. Пространство на диске будет освобождено отложенно. В Windows поведение иное: попытка удалить открытый файл обычно завершается ошибкой ERROR_SHARING_VIOLATION.
Ответ 18+ 🔞
А, ну это классика, ёпта! Сейчас объясню на пальцах, как это в Линуксе работает, а то народ иногда охуевает, когда файл удалил, а место на диске не освободилось.
Смотри, тут вся магия в том, как файловая система устроена. Представь, что у тебя есть сам файл с данными — это как бы «тело» (inode), а имя файла в папке — это просто «табличка» на нём. Так вот, когда ты делаешь unlink(), ты срываешь эту табличку, но само тело-то ещё живое, если кто-то за него держится!
Что происходит, по пунктам:
- Процесс Б говорит системе: «Отвяжи имя
file.txtот этого inode!» Система отвечает: «Окей, хуй с горы — табличку убрал, вlsего больше нет». - Но если процесс А уже открыл этот файл раньше и держит его дескриптор — то данные на диске не стираются! Inode и все блоки лежат себе спокойно, и процесс А может через свой открытый дескриптор читать и писать в этот файл, как ни в чём не бывало.
- Окончательно файл отправится в ад только когда процесс А закроет свой дескриптор, и счётчик ссылок на inode упадёт в ноль. Вот тогда система скажет: «А, ну раз никто не держит — тогда нахуй не нужен» и физически освободит место.
Пример на C++ (системные вызовы POSIX):
// Процесс А (читатель)
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
int main() {
int fd = open("testfile.txt", O_RDONLY);
if (fd == -1) { /* обработка ошибки */ }
char buffer[256];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
std::cout << "Прочитано: " << bytes_read << " байт. Файл открыт.n";
// В этот момент другой процесс может выполнить unlink("testfile.txt")
// Файл "исчез" из директории, но мы можем продолжать чтение.
lseek(fd, 0, SEEK_SET); // Вернуться к началу файла
bytes_read = read(fd, buffer, sizeof(buffer)); // Чтение все еще работает!
sleep(10); // Имитация долгой работы с файлом
close(fd); // ТЕПЕРЬ данные файла могут быть физически удалены с диска.
return 0;
}
Ключевой момент, бля: В этом и есть вся прелесть — можно спокойно обрабатывать, например, лог-файлы, не боясь, что какой-нибудь распиздяй его удалит в процессе. Место освободится потом, когда ты сам файл закроешь. А вот в Windows, ядрёна вошь, всё по-другому — там попробуй удали открытый файл, получишь ошибку ERROR_SHARING_VIOLATION и пойдёшь нахуй. Так что тут наш подход — просто овердохуища удобнее.