来自:编程珠玑在Linux中,你有没有天真地以为用rm删除一个文件,占用的空间就会被释放?事情可能并不总是如你所愿。生成指定大小的随机内容文件。我们先看看当前挂载的各个目录的空间大小:$df-h/dev/sda11454M280M147M66%/boot这里我选择其中一个结果显示(可以选择任意挂载目录),然后准备在/boot下生成一个文件。首先,我们生成一个50M的文件:$ddif=/dev/urandomof=/boot/test.txtbs=50Mcount=1至此,我们生成了一个50M的文件,接下来看boot:$df-h/dev/sda11454M312M115M74%/boot这里不用关心多少,只需要注意,/boot下的文件数量增加了。测试程序:#include#includeintmain(void){FILE*fp=NULL;fp=fopen("/boot/test.txt","rw+");if(NULL==fp){perror("打开文件失败");返回-1;}while(1){//什么都不做sleep(1);}fclose(fp);return0;}至于程序本身,它什么都不做,实际是打开一个文件,然后一直循环。编译运行:$gcc-oopenFileopenFile.c$./openFile另开一个窗口,删除test.txt:$rm/boot/test.txt再看看引导空间:$df-hdev/sda11454M312M115M74%/boot咦?空间的大小完全没有变化!!明明是用rm删除的?我们把openFile程序停掉再看:$$df-h/dev/sda11454M280M147M66%/boot好了,空间马上就释放了,也就是我们的文件按预期被删除了。什么情况下文件会被删除?实际上,只有当一个文件的引用计数为0(包括硬链接数)时,才有可能调用unlink删除,只要不为0,就不会被删除。所谓删除无非就是删除文件名到inode的链接。只要不改写新数据,磁盘上的块数据块就不会被删除。因此,你会看到即使库被删除跑掉了,一些数据还是可以恢复的。也就是说,当一个程序打开一个文件(获取文件描述符)时,它的引用计数会+1。rm虽然看起来是删除文件,但实际上只会将引用计数减1,但是因为引用计数不为0,所以不会删除文件。结构inode{structhlist_nodei_hash;/*指向哈希列表的指针*/structlist_headi_list;/*支持开发IO列表*/structlist_headi_sb_list;/*超级块的inode列表*/structlist_headi_dentry;项目对象链头*/unsignedlongi_ino;/*索引节点号*/atomic_ti_count;/*引用计数*/unsignedinti_nlink;/*硬链接数*/关于它的细节有很多(比如硬链接数也会影响文件是否被删除),这里就不展开了。如何释放已删除文件占用的空间?关于release,前面说了,重启打开文件的进程即可。但是有没有办法找出哪些文件已被删除,但仍被某些进程打开?自然有一个方法:$lsof|grepdeleted标记为删除的文件就是这样的文件。其实在前面的例子中,我们也很容易观察到(openFile程序运行,test.txt文件被删除):$ls-al/proc/`pidofopenFile`/fdtotal0lrwx------1rootroot64May409:270->/dev/pts/25lrwx------1rootroot64May409:271->/dev/pts/25lrwx------1root根64May409:272->/dev/pts/25lrwx------1rootroot64May409:273->/boot/test.txt(已删除)你看到test.txt了吗有后面也删了字。既然说了这种情况下文件并没有被删除,那还能恢复吗?它实际上仍然是可读的。总结其实这种文件被删除了,它经常出现在程序的日志文件中。也许你有一个计划任务要清理程序产生的日志文件,但如果程序本身忘记关闭句柄,就会导致磁盘空间不足。释放,最后,你以为文件已经删除了,但是磁盘还是被占用了。因此,养成一个好习惯。打开文件后,记得在不使用时关闭文件描述符。如果你发现大量的文件被删除了,但是空间并没有恢复正常,那么你不妨检查一下是否有打开这些文件的程序。