I was told, that mmap() might be in trouble, if someone deletes the original file. I was wondering if that really happens. So i created some little test-program. I am using linux.
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int, char**)
{
char const * const fileName = "/tmp/demo-file.dat";
size_t size;
{
struct stat st;
stat(fileName, &st);
size = st.st_size;
}
int fd = open(fileName, O_RDWR);
if (fd == -1)
{
std::cout << "open() failed, errno = " << errno << ":" << strerror(errno) << std::endl;
return (-1);
}
else
{
std::cout << "open() done (ok)" << std::endl;
}
for (int i = 20; i > 0; --i)
{
std::cout << "file open()'ed, wait #" << i << " seconds before mmap()" << std::endl;
sleep(1);
}
void *data = mmap((void*)0L, size, PROT_READ, MAP_SHARED, fd, (off_t)0);
if (data == (void*)-1)
{
std::cout << "mmap() failed, errno = " << errno << ":" << strerror(errno) << std::endl;
}
else
{
std::cout << "mmap() done (ok)" << std::endl;
}
for (int i = 20; i > 0; --i)
{
std::cout << "going to close() socket in #" << i << " seconds" << std::endl;
sleep (1);
}
close(fd);
for (int i = 30; i > 0; --i)
{
std::cout << "going to umap() files in #" << i << " seconds (still accessing the data)" << std::endl;
for (unsigned int x = 0; x < size; ++x)
{
char cp = *(char*) (data + x);
(void) cp;
}
sleep(1);
}
munmap(data, size);
for (int i = 30; i > 0; --i)
{
std::cout << "going to terminate #" << i << " seconds" << std::endl;
sleep(1);
}
return 0;
}
Whenever i delete the file - after the open() operation - it doesn't have negative impact to then mmap(). I can still acess the data in the test program. When i delete the file right after close(), but before mmap(), it works. I can also still see the old file in the /proc/[pid]/fd/ area:
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
The rest of the program works.
Even when i delete the file after the close() it still succeeds to access the mmap() data. However in both cases, after the close() i cannot see the
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
anymore. (btw: where is then noted, that this file "still exists somehow"?)
So is it the opposite, that it is guaranteed, that mmap() will still be able to operate on the data, even if the file was manually deleted (in a shell or by some other process)?
Here's what's happening.
The first thing to check is
$ls -i /tmp/demo-file.dat
65 /tmp/demo-file.dat
Note the inode number of the file is 65.
On starting the program, here's what it has in its lsof
output (apart from other entries not relevant to the current discourse)
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat
This is a result of the open()
that's been done. Note that the inode number is the same as the other file. The open()
has increased the ref count on the same inode. Also, note that REG
indicates a regular file.
Now if the file is deleted (using rm
etc.), here's what the lsof
looks like
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
This is expected since the file that was opened has been deleted but the handle that to its inode still is open in the process.
Moving on to the mmap, and here's the lsof
output
a.out 29271 zoso DEL REG 0,21 65 /tmp/demo-file.dat
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
Now there's another new entry but note that this is of type DEL
which indicates (lifting from lsof man page):
''DEL'' for a Linux map file that has been deleted;
Since lsof
can't stat the original file anymore, it puts this mapping as DEL
with no size of course, yet note that the inode number still remains the same i.e 65.
Now after close()
has been called on the fd here's what lsof
shows
a.out 29271 zoso DEL REG 0,21 65 /tmp/demo-file.dat
Note that the (deleted)
entry is gone since that fd to a REG
file has been closed and now only the mmap'd memory remains.
After munmap()
this entry too is gone (no more references to /tmp/demo-file.dat
and finally the program ends.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With