删除文件后是否可以使用fread?

时间:2009-02-03 13:47:36

标签: c

我使用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

4 个答案:

答案 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)。这样只有你可以访问文件的数据,没有其他过程可以。

即使另一个进程创建了具有相同名称的其他文件,它们的新文件也与原始文件没有任何共同之处。