Как я могу удалить файл на его завершение в C++ на Linux?

Я хочу для файла быть удаленным из диска только, когда он закрывается. Вплоть до той точки другие процессы должны смочь видеть файл на диске и считать его содержание, но в конечном счете после завершения файла, это должно быть удалено из диска и больше не видимое на диске к другим процессам.

8
задан WilliamKF 5 July 2010 в 19:11
поделиться

6 ответов

Откройте файл, затем удалите его пока он открыт. Другие процессы смогут использовать файл, но как только все ручки к файлу будут закрыты, он будет удален.

Edit: основываясь на комментариях, добавленных WilliamKF позже, это не достигнет того, чего он хочет - он будет держать сам файл, пока все ручки к нему не будут закрыты, но запись в каталоге для имени файла исчезнет, как только вы вызовете unlink/remove.

10
ответ дан 5 December 2019 в 11:22
поделиться

Открытые файлы в Unix подсчитываются по ссылкам. Каждое open(2) увеличивает счетчик, каждое close(2) уменьшает его. Счетчик является общим для всех процессов в системе.

Затем есть счетчик ссылок для дискового файла. Совершенно новый файл получает счетчик, равный единице. Счетчик увеличивается с помощью link(2) системного вызова. Вызов unlink(2) уменьшает его. Файл удаляется из файловой системы, когда счетчик падает до нуля.

Единственный способ выполнить то, что вы просите, - открыть файл в одном процессе, а затем unlink(2) его. Другие процессы смогут open(2) или stat(2) его между open(2) и unlink(2). Если предположить, что у файла была только одна ссылка, она будет удалена, когда все процессы, у которых он был открыт, закроют его.

2
ответ дан 5 December 2019 в 11:22
поделиться

Не уверен, но можно попробовать remove, но это больше похоже на c-стиль.

Maybe boost::filesystem::remove?

bool remove( const path & ph );

Precondition: !ph.empty()

Returns: Значение exists( ph ) до установления постусловия.

Постусловие: !exists( ph )

Бросок: if ph.empty() || (exists(ph)) && is_directory(ph) && !is_empty(ph)). См. обоснование пустого пути.

Примечание: Символические ссылки сами по себе удаляются, а не то, на что они указывают на что они указывают.

Обоснование: Не выбрасывается, когда !exists( ph ), потому что не бросает:

Работает правильно, если ph является висячей символическая ссылка. Немного проще в использовании для многих распространенных случаев. Является немного более высокоуровневым поскольку подразумевает использование семантики постусловий, а не семантики эффектов, которая будет определены на несколько более низком уровне терминах взаимодействия с операционной системой. Однако при этом происходит небольшое снижение безопасности, потому что некоторые ошибки будут проскальзывать мимо, которые в противном случае были бы обнаружены. Например, неправильно написанное имя пути может необнаруженной в течение длительного времени.

Первоначальная версия библиотеки выбрасывала исключение, когда путь не существует; это было изменено, чтобы отразить жалобы пользователей.

Вы можете создать класс-обертку, который подсчитывает ссылки, используя один из описанных выше методов для удаления файла.

class MyFileClass{

    static unsigned _count;
 public:
    MyFileClass(std::string& path){
     //open file with path
     _count++;
    }

    //other methods

    ~MyFileClass(){

        if (! (--_count)){

          //delete file
        }

     }

    };

   unsigned MyFileClass::_count = 0; //elsewhere
0
ответ дан 5 December 2019 в 11:22
поделиться

Использование unlink

#include <unistd.h>

int unlink(const char *pathname); 

unlink () удаляет имя из файловая система. Если бы это имя было последним ссылка на файл, и у процессов нет файл открыть файл удаляется и пространство, которое он использовал, сделано доступны для повторного использования.

Если имя было последней ссылкой на файл, но все процессы по-прежнему имеют файл открыть файл останется в существование до последнего файла ссылающийся на него дескриптор закрыт.

Если в названии упоминается символический ссылка ссылка удалена.

Если имя относится к сокету, fifo или устройство имя для него удалено но процессы, имеющие объект open может продолжать его использовать.

0
ответ дан 5 December 2019 в 11:22
поделиться

Я думаю, вам нужно расширить ваше понятие "закрытия файла" за пределы fclose или std::fstream::close до того, что вы собираетесь делать. Это может быть так же просто, как

class MyFile : public std::fstream {
  std::string filename;
public:
  MyFile(const std::string &fname) : std::fstream(fname), filename(fname) {}
  ~MyFile() { unlink(filename); }
}

или это может быть что-то гораздо более сложное. Насколько я знаю, это может быть даже намного проще - если вы закрываете файлы только в одном или двух местах вашего кода, лучшим решением может быть просто отвязать файл там (или использовать boost::filesystem::remove, как предлагает Том).

Однако, если все, чего вы хотите добиться, это чтобы процессы, запущенные из вашего процесса, могли использовать этот файл, то, возможно, вам вообще не нужно держать его на диске. forked процессы наследуют открытые файлы. Не забудьте дублировать их, чтобы поиск в дочернем процессе не повлиял на позицию в родительском или наоборот.

0
ответ дан 5 December 2019 в 11:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: