Что произойдет, если процесс А читает файл, а процесс Б пытается его удалить?

Ответ

В Linux и других Unix-подобных системах файловая подсистема отделяет запись в каталоге (имя файла) от самих данных на диске (inode). Когда процесс открывает файл, ядро увеличивает счетчик ссылок для соответствующего inode.

Поведение:

  1. Процесс Б успешно выполняет системный вызов unlink("file.txt").
  2. Имя файла (file.txt) немедленно удаляется из каталога. Команда ls его больше не покажет.
  3. Однако, если процесс А уже открыл этот файл (имеет открытый файловый дескриптор), данные на диске не уничтожаются. Inode и блоки данных остаются доступными для процесса А через его дескриптор.
  4. Файл будет окончательно удален с диска, только когда процесс А закроет файл (и счетчик ссылок на 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(), ты срываешь эту табличку, но само тело-то ещё живое, если кто-то за него держится!

Что происходит, по пунктам:

  1. Процесс Б говорит системе: «Отвяжи имя file.txt от этого inode!» Система отвечает: «Окей, хуй с горы — табличку убрал, в ls его больше нет».
  2. Но если процесс А уже открыл этот файл раньше и держит его дескриптор — то данные на диске не стираются! Inode и все блоки лежат себе спокойно, и процесс А может через свой открытый дескриптор читать и писать в этот файл, как ни в чём не бывало.
  3. Окончательно файл отправится в ад только когда процесс А закроет свой дескриптор, и счётчик ссылок на 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 и пойдёшь нахуй. Так что тут наш подход — просто овердохуища удобнее.