Search code examples
c++cfilefilesystemslsof

Creating and deleting files from C/C++


I seem to be confused about how file removal works on Linux (same behavior on Mac OS X). The following code writes a 1GB file and then immediately deletes it. It does so 1024 times. I thought that since the file is closed, it would be immediately removed (space reclaimed and maybe even the file descriptor recycled). Instead, if I look at lsof, the file is still claimed as owned by the process (with (deleted) appended to it). If I look at df, the space is still used up. Eventually, the process dies from either exhausting the number of allowed open files, a limit I can raise, or just running out of space.

What's the right way to do this? Can I actually delete the file before the process terminates (and reclaim its space), or is this a hopeless exercise and I need another design for my code?

#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <fcntl.h>

#include <iostream>

int main()
{
    size_t n = 1024*1024*1024;
    void* buffer = malloc(n);
    std::cout << "Buffer created" << std::endl;

    for (unsigned i = 0; i < 1024; ++i)
    {
        char filename[50] = "STORAGE.XXXXXX";
        mkstemp(filename);
        std::cout << filename << std::endl;
        int fh = open(filename, O_WRONLY | O_SYNC, 0600);
        write(fh, buffer, n);
        close(fh);
        remove(filename);
    }
    free(buffer);
    sleep(60);
}

lsof:

test-remo 29251 ...    3u   REG   8,51 1073741824  9307914 .../tmp/STORAGE.Tyj4oG (deleted)
test-remo 29251 ...    4u   REG   8,51 1073741824  9308254 .../tmp/STORAGE.fBkF5b (deleted)
test-remo 29251 ...    5u   REG   8,51 1073741824  9308030 .../tmp/STORAGE.xfJ9P0 (deleted)
test-remo 29251 ...    6u   REG   8,51 1073741824  9308538 .../tmp/STORAGE.0C6oea (deleted)
test-remo 29251 ...    7u   REG   8,51 1073741824  9306147 .../tmp/STORAGE.w9dPzC (deleted)
test-remo 29251 ...    8u   REG   8,51 1073741824  9308311 .../tmp/STORAGE.mIwcpq (deleted)
test-remo 29251 ...    9u   REG   8,51 1073741824  9309004 .../tmp/STORAGE.srTZfy (deleted)
test-remo 29251 ...   10u   REG   8,51 1073741824  9309284 .../tmp/STORAGE.xjQQ4Y (deleted)
test-remo 29251 ...   11u   REG   8,51 1073741824  9309291 .../tmp/STORAGE.ioyPxI (deleted)
test-remo 29251 ...   12u   REG   8,51 1073741824  9307415 .../tmp/STORAGE.saYo2L (deleted)
test-remo 29251 ...   13u   REG   8,51 1073741824  9307810 .../tmp/STORAGE.ylW467 (deleted)
test-remo 29251 ...   14u   REG   8,51 1073741824  9308666 .../tmp/STORAGE.lUYnWN (deleted)
test-remo 29251 ...   15u   REG   8,51 1073741824  9309678 .../tmp/STORAGE.1rZM4M (deleted)
test-remo 29251 ...   16u   REG   8,51 1073741824  9309702 .../tmp/STORAGE.wdggra (deleted)
test-remo 29251 ...   17u   REG   8,51 1073741824  9309687 .../tmp/STORAGE.qczYAS (deleted)
test-remo 29251 ...   18u   REG   8,51 1073741824  9309732 .../tmp/STORAGE.u0IxKV (deleted)
test-remo 29251 ...   19u   REG   8,51 1073741824  9309708 .../tmp/STORAGE.6SiMpi (deleted)
test-remo 29251 ...   20u   REG   8,51 1073741824  9308649 .../tmp/STORAGE.URky5Z (deleted)
test-remo 29251 ...   21u   REG   8,51 1073741824  9309740 .../tmp/STORAGE.j8wEq2 (deleted)
test-remo 29251 ...   22u   REG   8,51 1073741824  9309677 .../tmp/STORAGE.Wj5rco (deleted)
test-remo 29251 ...   23u   REG   8,51 1073741824  9309828 .../tmp/STORAGE.I38ln3 (deleted)
test-remo 29251 ...   24u   REG   8,51 1073741824  9309839 .../tmp/STORAGE.ent8I1 (deleted)
test-remo 29251 ...   25u   REG   8,51 1073741824  9309843 .../tmp/STORAGE.1361nk (deleted)
test-remo 29251 ...   26u   REG   8,51 1073741824  9309824 .../tmp/STORAGE.ue2WkW (deleted)
test-remo 29251 ...   27u   REG   8,51 1073741824  9312037 .../tmp/STORAGE.4MdKsR (deleted)
test-remo 29251 ...   28u   REG   8,51 1073741824  9312042 .../tmp/STORAGE.EgDft5 (deleted)
test-remo 29251 ...   29u   REG   8,51 1073741824  9312059 .../tmp/STORAGE.NRcqlE (deleted)
test-remo 29251 ...   30u   REG   8,51 1073741824  9309847 .../tmp/STORAGE.cF9qYw (deleted)
test-remo 29251 ...   31u   REG   8,51 1073741824  9312103 .../tmp/STORAGE.wzfhSI (deleted)
test-remo 29251 ...   32u   REG   8,51 1073741824  9312120 .../tmp/STORAGE.hfdv1d (deleted)
test-remo 29251 ...   33u   REG   8,51 1073741824  9312090 .../tmp/STORAGE.kSX2D4 (deleted)
test-remo 29251 ...   34u   REG   8,51 1073741824  9309813 .../tmp/STORAGE.FWKVGf (deleted)
test-remo 29251 ...   35u   REG   8,51 1073741824  9312148 .../tmp/STORAGE.CYPGGL (deleted)
test-remo 29251 ...   36u   REG   8,51 1073741824  9312171 .../tmp/STORAGE.it4bmC (deleted)
test-remo 29251 ...   37u   REG   8,51 1073741824  9312145 .../tmp/STORAGE.IGSzVO (deleted)
test-remo 29251 ...   38u   REG   8,51 1073741824  9312228 .../tmp/STORAGE.CMSOil

Solution

  • When you're invoking mkstemp, it not only creates a temporary file, it also opens it and returns a filehandle.

    #include <unistd.h>
    #include <cstdlib>
    #include <cstdio>
    #include <fcntl.h>
    
    #include <iostream>
    
    int main()
    {
        size_t n = 1024*1024*1024;
        void* buffer = malloc(n);
        std::cout << "Buffer created" << std::endl;
    
        for (unsigned i = 0; i < 1024; ++i)
        {
            char filename[50] = "STORAGE.XXXXXX";
    
            int fh;
            fh = mkstemp(filename);
            // close(fh)
            std::cout << filename << std::endl;
            // fh = open(filename, O_WRONLY | O_SYNC, 0600);
            write(fh, buffer, n);
            close(fh);
            remove(filename);
        }
        free(buffer);
        sleep(60);
    }
    

    If you want to open it with WRONLY and SYNC, then you have to first close the returned filehandle, and then re-open it, if you so desire. In that case, just remove the // comment marks before close and open, or use mkostemp instead.

    NAME
           mkstemp, mkostemp, mkstemps, mkostemps - create a unique temporary file
    
    SYNOPSIS
           #include <stdlib.h>
    
           int mkstemp(char *template);
           int mkostemp(char *template, int flags);
    
    
    RETURN VALUE
         On success, these functions return the file descriptor of the  temporary  file.
         On error, -1 is returned, and errno is set appropriately.