2010-07-05 26 views
7

Tôi chỉ muốn một tệp sẽ bị xóa khỏi đĩa khi nó bị đóng. Cho đến thời điểm đó, các quy trình khác sẽ có thể xem tệp trên đĩa và đọc nội dung của nó, nhưng cuối cùng sau khi đóng tệp, tệp sẽ bị xóa khỏi đĩa và không còn hiển thị trên đĩa cho các quy trình khác.Làm cách nào để xóa một tệp khi đóng trong C++ trên Linux?

+6

Bạn có nghĩa là tất cả quá trình sẽ có thể xem ** tên ** của tệp trong thư mục của nó?Bởi vì nếu như bạn nói, những gì bạn cần để xem chỉ là ** nội dung **, sau đó một 'rm' của tên tệp _does_ để chúng có thể sử dụng được bởi tất cả các tiến trình có tệp đang mở và tệp sẽ biến mất khi quá trình cuối cùng đóng nó để nó không mở trong bất kỳ quá trình nào. –

+0

Có, phải xem tên tệp, sao cho bất kỳ quy trình mới nào được gọi sau khi xóa sẽ thấy tệp trên đĩa cho đến khi quá trình gốc xóa tệp thoát. – WilliamKF

+1

Từ sự hiểu biết của tôi về ngữ nghĩa hệ thống tập tin Unix, điều này là không thể, ít nhất là không có điều kiện chủng tộc. Bạn có thể làm điều gì đó với một công việc định kỳ chạy 'lsof', nhưng điều đó khiến tôi như một ý tưởng tồi. Bạn đang thực sự cố gắng làm gì? – Novelocrat

Trả lời

8

Mở tệp, sau đó xóa tệp trong khi mở. Các quy trình khác sẽ có thể sử dụng tệp, nhưng ngay khi tất cả các xử lý tệp được đóng, nó sẽ bị xóa.

Chỉnh sửa: dựa trên các ý kiến ​​mà WilliamKF thêm vào sau, điều này sẽ không thực hiện được những gì anh ta muốn - nó sẽ tự giữ nguyên tập tin cho đến khi tất cả các chốt được đóng, nhưng mục nhập tên tệp sẽ biến mất ngay khi bạn gọi unlink/remove.

+0

Sử dụng hủy liên kết()? – WilliamKF

+2

@WilliamKF: Bạn có thể sử dụng 'hủy liên kết' hoặc' xóa'. –

+5

Xin lỗi, nhưng William cho biết tên tệp phải được hiển thị trong hệ thống tệp. Chiến lược “xóa, nhưng giữ nó mở” sẽ không hoạt động vì điều đó - nó sẽ để lại tập tin ở đó, nhưng vì số lượng thư mục chỉ vào nó (trong đó có thể có nhiều hơn!) Là không, không quá trình chưa mở nó sẽ tìm thấy nó. (Không phải những người khác sẽ thấy một mục trong hệ thống tập tin.) –

0

Không chắc chắn, nhưng bạn có thể thử remove nhưng trông giống như kiểu c.

Có thể boost::filesystem::remove?

bool remove(const path & ph); 

kiện tiên quyết: ph.empty()

Returns: Giá trị của tồn tại (ph) trước khi thành lập hậu.

Điều kiện:! Tồn tại (ph)

Ném: nếu ph.empty() || (tồn tại (ph) & & is_directory (ph) & &! is_empty (ph)). Xem lý do đường dẫn trống.

Lưu ý: Liên kết tượng trưng là chính mình bị xóa, thay vì những gì họ trỏ tới để bị xóa.

Lý do: Không vứt khi tồn tại (ph) vì không ném:

Làm việc một cách chính xác nếu ph là treo lủng lẳng liên kết tượng trưng. Là hơi dễ sử dụng hơn cho nhiều trường hợp sử dụng phổ biến trường hợp. Cao hơn một chút là vì nó ngụ ý sử dụng ngữ nghĩa sau điều kiện thay vì ngữ nghĩa hiệu ứng, sẽ là được chỉ định ở mức độ thấp hơn điều khoản tương tác với hệ điều hành . Tuy nhiên, có giảm nhẹ về an toàn vì một số lỗi sẽ bị trượt nếu không, nếu không, sẽ bị phát hiện. Ví dụ: tên đường dẫn sai chính tả có thể bị không bị phát hiện trong một thời gian dài.

Phiên bản ban đầu của thư viện đã ném một ngoại lệ khi đường dẫn đã làm không tồn tại; nó đã được thay đổi để phản ánh khiếu nại của người dùng.

Bạn có thể tạo lớp bao bọc tính tham chiếu, sử dụng một trong các phương pháp trên để xóa tệp.

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

Sử dụng unlink

#include <unistd.h> 

int unlink(const char *pathname); 

unlink() xóa một tên từ hệ thống tập tin. Nếu tên đó là liên kết cuối cùng vào tệp và không có quy trình nào có thì tệp mở tệp sẽ bị xóa và không gian đang sử dụng được tạo có sẵn để sử dụng lại.

Nếu tên là mắt xích cuối cùng vào một tập tin nhưng bất kỳ quy trình vẫn có file mở file sẽ vẫn tồn tại cho đến khi mô tả tập tin cuối cùng đề cập đến nó được đóng lại.

Nếu tên được gọi là liên kết tượng trưng , liên kết sẽ bị xóa.

Nếu tên được gọi đến một ổ cắm, nămo hoặc thiết bị tên cho nó bị xóa nhưng các quá trình có đối tượng mở có thể tiếp tục sử dụng nó.

2

Mở tệp trong Unix được tính tham chiếu. Mỗi open(2) tăng số lượt truy cập, mỗi số close(2) đều giảm giá trị đó. Bộ đếm được chia sẻ bởi tất cả các tiến trình trên hệ thống.

Sau đó, có một số liên kết cho tệp đĩa. Tệp hoàn toàn mới có số lượng là một. Số đếm được tăng lên bởi cuộc gọi hệ thống link(2). Các unlink(2) giảm nó. Tệp được xóa khỏi hệ thống tệp khi số này giảm xuống 0.

Cách duy nhất để thực hiện những gì bạn yêu cầu là mở tệp trong một quá trình, sau đó unlink(2) nó. Các quy trình khác sẽ có thể open(2) hoặc stat(2)giữa open(2)unlink(2). Giả sử tệp chỉ có một liên kết, tệp sẽ bị xóa khi tất cả các quá trình để mở tệp đó.

0

Tôi nghĩ bạn cần mở rộng khái niệm “đóng tệp” vượt quá fclose hoặc std::fstream::close cho bất kỳ điều gì bạn định làm. Điều đó có thể đơn giản như

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

hoặc nó có thể phức tạp hơn nhiều. Đối với tất cả những gì tôi biết, nó thậm chí có thể đơn giản hơn nhiều - nếu bạn đóng các tệp chỉ ở một hoặc hai vị trí trong mã của bạn, điều tốt nhất để làm có thể chỉ đơn giản là unlink tệp đó (hoặc sử dụng boost :: filesystem :: remove, như Tom gợi ý).

OTOH, nếu tất cả những gì bạn muốn đạt được là các quá trình bắt đầu từ quá trình của bạn có thể sử dụng tệp, bạn có thể không cần phải giữ nó nằm xung quanh trên đĩa. fork quy trình ed kế thừa các tệp đang mở. Đừng quên để dup họ, vì sợ rằng tìm kiếm trong các con ảnh hưởng đến vị trí trong phụ huynh hoặc ngược lại.

Các vấn đề liên quan