Linux下打开文件后没有关闭的后果分析

这两天测试文件操作的性能,发现了有的地方打开文件后没有关闭。不关闭文件的后果是比较严重的,尤其是对服务器端程序来说更为严重。那这样会有什么问题呢?
1.不能再打开新文件.
打开大量文件并且不关闭, 很快会达到进程最大允许打开的文件数限制,这样就不能再打开文件。
在Linux上,可以通过ulimit -n 来查看和更改当前session的限制数,比如在我的机器上是:

$ ulimit -n
7168
$ ulimit -n 10000
10000

也可以通过修改/etc/security/limits.conf来永久性的修改限制数

2. 硬盘空间被占满。
如果文件被打开后,再被删除,在文件不被关闭的情况下,原文件占用的空间不会被释放,这样可能会出现磁盘空间不足的问题。我碰到的实际例子是 “安全删除文件”: 先将文件全部内容填充为0,再删除文件。问题是在把文件内容填充为0后没有关闭文件,所以虽然文件在后面被删除了,但由于是服务器端程序,进程不会终止,所以空间并没有被释放。
下面摘自于unlink函数的manual:

unlink() deletes a name from the file system. If that name was the
last link to a file and no processes have the file open the file is
deleted and the space it was using is made available for reuse.

If the name was the last link to a file but any processes still have
the file open the file will remain in existence until the last file
descriptor referring to it is closed.

下面这个程序可以对这一点进行测试:

#include <stdio.h>
#include <unistd.h>
#include <malloc.h>

int main(int argc, char** argv){
  if(argc < 3){
    printf("Copy a file to target, then delete the target file without close"
            "Usage: %s <filename> <target filename>n", argv[0]);
    return -1;
  }
  
  int size;
  char* buf = malloc(1024 * 16);
  FILE *fp = fopen(argv[1], "r");
  FILE *fp2 = fopen(argv[2], "w+");

  do {
    size = fread(buf, 1, 1024*16, fp);
    fwrite(buf, 1, size, fp2);
  } while(!feof(fp));

  free(buf);
  fclose(fp);
  remove(argv[2]);

  printf("Press Ctrl +c to stop the program.n");

  while(1){
    sleep(100);
  }

  return 0;
}

测试步骤:
找一个比较大的测试文件,以LibreOffice_4.1.0_Linux_x86-64_rpm.tar.gz 为例

$ ls -lh LibreOffice_4.1.0_Linux_x86-64_rpm.tar.gz
-rw-rw-r-- 1 twer twer 198M Sep  5 12:36 LibreOffice_4.1.0_Linux_x86-64_rpm.tar.gz

$ df /dev/sda1
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/sda1      464250648 45744328 394923704  11% /

在一个新的命令行窗口上执行测试程序

$ ./a.out LibreOffice_4.1.0_Linux_x86-64_rpm.tar.gz t/libreoffice.tar.gz
Press Ctrl +c to stop the program.

再查看当前的分区使用情况

$ df /dev/sda1
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/sda1      464250648 45946800 394721232  11% /

通过Ctrl + c 关闭测试程序, 再查看当前的分区使用情况

$ df /dev/sda1
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/sda1      464250648 45744328 394923704  11% /

Leave a Reply

Your email address will not be published.