2010-07-05 85 views
7

我希望文件僅在關閉時才從磁盤中刪除。到那時爲止,其他進程應該能夠看到磁盤上的文件並讀取其內容,但最終在文件關閉後,應該從磁盤中刪除並且不再在其他進程上看到該磁盤。如何在Linux上使用C++關閉文件時刪除文件?

+6

你的意思是說所有進程都應該能夠在其目錄中看到該文件的**名稱**嗎?因爲如你所說,如果你需要它們看到的只是**內容**,那麼文件名稱的一個'rm' _does_會讓所有打開該文件的進程都可用,並且當文件最後一個過程將其關閉,以便在任何過程中都不會打開。 – 2010-07-05 19:08:12

+0

是的,必須看到文件的名稱,以便刪除後調用的任何新進程都能看到磁盤上的文件,直到刪除該文件的原始進程退出。 – WilliamKF 2010-07-05 19:10:07

+1

從我對Unix文件系統語義的理解來看,這是不可能的,至少不是沒有競爭條件。你可能可以通過運行'lsof'的定期作業來做些事情,但這是一個糟糕的主意。你究竟在努力完成什麼? – Novelocrat 2010-07-05 19:24:18

回答

8

打開文件,然後刪除它它是開放的。其他進程將能夠使用該文件,但只要文件的所有句柄都關閉,它就會被刪除。

編輯:基於評論WilliamKF後來補充說,這將不會達到他想要的 - 它會保留文件本身,直到它的所有句柄關閉,目錄條目的文件名將在您致電unlink/remove後立即消失。

+0

使用unlink()? – WilliamKF 2010-07-05 19:08:14

+2

@WilliamKF:你可以使用'unlink'或'remove'。 – 2010-07-05 19:09:24

+5

對不起,但威廉說文件名必須在文件系統中可見。 「刪除但保持打開」策略將不起作用 - 它會將文件保留在那裏,但是由於指向它的目錄項(其中可能有多個目錄項)的數量爲零,因此無過程尚未打開將會找到它。 (其他人也不會在文件系統中看到一個條目。) – 2010-07-05 19:16:49

0

不確定,但你可以嘗試remove,但它看起來更像C風格。

也許boost::filesystem::remove

bool remove(const path & ph); 

前提條件:ph.empty()

返回:存在(pH值)的值建立 後置條件之前 。

後置條件:存在(pH值)

拋出:如果ph.empty()|| (存在(ph) & & is_directory(ph)& &!is_empty(ph))。 查看空路徑理由。

注意:刪除符號鏈接本身 ,而不是它們指向 被刪除。

理由:因爲不扔不扔時 存在(pH值):

正常工作,如果ph爲懸空 符號鏈接。 略爲易於使用,許多常見使用 的情況下。稍高級別的 因爲它意味着使用 後置條件語義,而不是 影響語義,這將在稍低級別來 指定與 操作系統交互的 條款。然而,由於某些 錯誤將會滑落,否則 將會被檢測到,所以安全性略有下降。例如, 拼寫錯誤的路徑名可能會長時間未檢測到 。

當路徑 不存在時,庫 的初始版本會引發異常;它被改爲反映用戶投訴 。

您可以創建一個包裝類來計算引用,使用上述方法之一來刪除de文件。

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

使用unlink

#include <unistd.h> 

int unlink(const char *pathname); 

的unlink()刪除從 文件系統的名稱。如果該名稱是最後一個 指向文件的鏈接,並且沒有進程具有 ,則會刪除該文件的打開文件,並且將使用的空間爲 可供重用。

如果這個名字的最後一個環節到 文件,但任何進程仍然有 文件打開該文件將保持在 存在,直到最後一個文件 描述指的是它是封閉的。

如果名稱引用符號 鏈接,鏈接將被刪除。

如果提到的插座的名稱,FIFO 或裝置它的名字被除去,其具有對象 開放可以繼續使用它 但過程。

2

Unix中的打開文件是引用計數的。每增加一個open(2)計數器,每個close(2)遞減計數。該計數器由系統上的所有進程共享。

然後有一個鏈接計數爲磁盤文件。全新的文件得到一個計數。系統調用將使計數增加link(2)unlink(2)遞減。當此計數降至零時,文件將從文件系統中刪除。

完成你所要求的唯一方法是在一個進程中打開文件,然後unlink(2)它。其他進程將能夠在open(2)stat(2)之間之間open(2)unlink(2)。假設該文件只有一個鏈接,它將在所有進程已將其關閉時刪除。

0

我認爲您需要將「關閉文件」的概念擴展到fclosestd::fstream::close以外的任何您打算執行的操作。這可能就像

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

或者它可能是更精細的東西。據我所知,它甚至可能更簡單 - 如果您只關閉代碼中的一兩個地方的文件,最好的做法可能是簡單地將unlink文件(或使用boost :: filesystem :: remove,正如湯姆所說)。

OTOH,如果你想實現的只是從你的進程開始的進程可以使用該文件,你可能不需要保持它在磁盤周圍。 ed進程繼承打開的文件。不要忘記dup他們,免得尋求孩子影響父母的位置,反之亦然。