mmap() после удаления файла
Мне сказали, что у mmap () могут возникнуть проблемы, если кто-то удалит исходный файл. Мне было интересно, если это действительно происходит. Итак, я создал небольшую тестовую программу. Я использую 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;
}
Всякий раз, когда я удаляю файл - после операции open () - он не оказывает негативного влияния на mmap (). Я все еще могу получить доступ к данным в тестовой программе. Когда я удаляю файл сразу после close (), но до mmap (), он работает. Я также все еще вижу старый файл в /proc/[pid]/fd/ area:
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
Остальная часть программы работает.
Даже когда я удаляю файл после close (), он все равно успешно обращается к данным mmap (). Однако в обоих случаях после закрытия () я не вижу
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
больше. (кстати: где тогда отмечается, что этот файл "все еще существует как-то"?)
Значит, наоборот, что гарантировано, что mmap () все еще сможет работать с данными, даже если файл был удален вручную (в оболочке или каким-либо другим процессом)?
1 ответ
Вот что происходит.
Первое, что нужно проверить, это
$ls -i /tmp/demo-file.dat
65 /tmp/demo-file.dat
Обратите внимание на номер индекса файла 65.
При запуске программы, вот что у нее есть lsof
вывод (кроме других записей, не относящихся к текущему дискурсу)
a.out 29271 ichakrab 3u REG 0,21 5 65 /tmp/demo-file.dat
Это результат open()
это было сделано. Обратите внимание, что номер индекса совпадает с другим файлом. open()
увеличил количество ссылок на тот же индекс. Также обратите внимание, что REG
указывает на обычный файл.
Теперь, если файл удален (используя rm
и т.д.), вот что lsof
похоже
a.out 29271 ichakrab 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
Это ожидаемо, так как открытый файл был удален, но дескриптор его inode все еще открыт в процессе.
Переходя к Mmap, и вот lsof
выход
a.out 29271 ichakrab DEL REG 0,21 65 /tmp/demo-file.dat
a.out 29271 ichakrab 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
Теперь есть еще одна новая запись, но обратите внимание, что это типа DEL
который указывает (снятие со страницы руководства lsof):
'' DEL '' для файла карты Linux, который был удален;
поскольку lsof
больше не может определить исходный файл, он отображает это отображение как DEL
конечно, без размера, но обратите внимание, что номер инода остается тем же, 65.
Теперь после close()
был вызван на FD вот что lsof
шоу
a.out 29271 ichakrab DEL REG 0,21 65 /tmp/demo-file.dat
Обратите внимание, что (deleted)
вход ушел, так как это FD к REG
файл был закрыт, и теперь остается только память mmap.
После munmap()
эта запись тоже пропала (больше нет ссылок на /tmp/demo-file.dat
и наконец программа заканчивается.