我使用fopen将文件流打开到一个非常大的文件。 在对该流执行任何读取操作之前,我使用unlink()删除了该文件。 而且,我能够阅读整个文件。
我猜测有一个与流关联的缓冲区,它保存文件的数据。但显然缓冲区有限制。这就是我选择大小为551126688字节或526MB的a_big_file的原因。
我想知道它背后的确切原因是什么。 这是我使用的测试代码。
#include <stdio.h>
#include <unistd.h>
int main(){
FILE *fp;
long long int file_size = 0;
int bytes_read = 0;
char buf[1];
fp = fopen("a_big_file", "r");
unlink("a_big_file");
while(0 != (bytes_read = fread(buf, 1, 1, fp))){
file_size += bytes_read;
}
printf("file_size is %llu\n", file_size);
return 0;
}
输出: file_size是551126688
答案 0 :(得分:17)
在Unix和类Unix操作系统中,文件实际上并没有消失,直到关闭它的最后一个打开文件句柄。对于临时文件,这是一个非常有用的技巧 - 如果您在打开文件时取消链接,该文件将不会被其他进程看到,并且一旦程序关闭,结束或将立即从系统中删除该文件。崩溃。这有助于防止孤立临时文件的泛滥。
实际上(在这里掩饰一些技术细节)会发生什么是Unix文件系统被引用计数。当您打开文件时,实际上您已连接到文件的inode(这是文件实际内容所在位置的真实指示)。但取消链接文件只会删除目录条目,因此该文件不再具有名称。文件系统只会回收文件空间(即inode),如果它不在任何目录条目中,并且没有人打开它。其他进程无法以普通方式打开它,因为它们无法将文件名映射到inode。
请注意,Unix文件系统允许多个目录条目指向同一个inode - 我们称之为“硬链接”。如果你执行“ls -l”,其中一个字段是指向同一个inode的硬链接数,如果你执行“ls -li”,则可以看到实际的inode地址。
答案 1 :(得分:9)
来自unlink的手册页:
unlink()从中删除名称 文件系统。如果那个名字是最后一个 链接到文件,没有进程 打开文件的文件被删除了 它正在使用的空间 可以重复使用。
如果名称是最后一个链接 一个文件,但任何进程仍然有 文件打开文件将保留 直到最后一个文件存在 引用它的描述符是 闭合。强>
粗体位解释了这种行为。 : - )
[编辑] BTW你应该在return语句之前用fclose()关闭文件... [/ edit]
答案 2 :(得分:3)
在某些系统(如Linux)上,只要进程仍然打开,您就可以轻松访问文件系统上没有名称的文件。
中有一个文件描述符列表/proc/<pid>/fd
修改:根据Paul Tomblin的评论,如果您与流程或root用户相同,则只能访问此目录。
例如:
# Create a file with cat
chris@shrubbery:~$ cat > MYFILE
Hello
# Suspend the process and find its pid
[1]+ Stopped cat > MYFILE
chris@shrubbery:~$ ps waux | grep cat
chris 1311 0.0 0.0 5088 668 pts/6 T 14:29 0:00 cat
chris 1313 0.0 0.0 5168 840 pts/6 R+ 14:29 0:00 grep cat
# Inspect the list of open files
chris@shrubbery:~$ cd /proc/1311/fd
chris@shrubbery:/proc/1311/fd$ ls -l
total 0
lrwx------ 1 chris chris 64 2009-02-03 14:29 0 -> /dev/pts/6
l-wx------ 1 chris chris 64 2009-02-03 14:29 1 -> /home/chris/MYFILE
lrwx------ 1 chris chris 64 2009-02-03 14:29 2 -> /dev/pts/6
# View MYFILE from the symlink on the /proc pseudofilesystem.
chris@shrubbery:/proc/1311/fd$ cat 1
Hello
# Delete the filename /home/chris/MYFILE
chris@shrubbery:/proc/1311/fd$ rm /home/chris/MYFILE
chris@shrubbery:/proc/1311/fd$ cat /home/chris/MYFILE
cat: /home/chris/MYFILE: No such file or directory
# But the process still has it open.
# The /proc system knows the original name was deleted
chris@shrubbery:/proc/1311/fd$ ls -l
total 0
lrwx------ 1 chris chris 64 2009-02-03 14:29 0 -> /dev/pts/6
l-wx------ 1 chris chris 64 2009-02-03 14:29 1 -> /home/chris/MYFILE (deleted)
lrwx------ 1 chris chris 64 2009-02-03 14:29 2 -> /dev/pts/6
# We can still view the file, useful for debugging.
chris@shrubbery:/proc/1311/fd$ cat 1
Hello
答案 3 :(得分:0)
在Linux
中,只有当文件的最后一个打开句柄关闭时才会删除文件。
人们通常以这种方式使用临时文件:mkstemp(3)
后跟立即unlink(2)
。这样只有你可以访问文件的数据,没有其他过程可以。
即使另一个进程创建了具有相同名称的其他文件,它们的新文件也与原始文件没有任何共同之处。