Chinaunix首页 | 论坛 | 博客
  • 博客访问: 440607
  • 博文数量: 177
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-22 19:16
文章分类

全部博文(177)

文章存档

2017年(1)

2016年(12)

2015年(112)

2014年(52)

我的朋友

分类: C/C++

2015-05-18 10:41:14

问题



   问题依然来源于参与的项目。参加产品的开发已有一年多的时间。项目过程中每周都会由SEG讨论一个星期内产品在客户使用过程中遇到的问题。最近的几次讨论总是围绕着我们的程序产生的临时文件。
   
由于程序运行过程中有些数据需要借助于文件形式进行转换,或需要临时保存下来,供稍后使用。在我们的程序运行过程中产生了可怕的问题,用户发现临时目录越来越占居磁盘空间(数据不断增加)~~


    也许部分人会认为,这不是程序的错误,临时文件可以让用户去手动删除,就像微软的操作系统一样,偶尔需要用户去释放一下系统空间。我想我们的程序应该尽量减轻用户的负担,这样用户才会乐于使用我们的产品,更何况部署在服务器网关的产品。

    作为临时文件,其应该被删除。检查我们的代码,发现逻辑上是正确的:1)创建文件;2)使用文件; 3)删除文件。那么为什么还会有临时文件存在呢?不是已经被删除了么?


解决方法



经过大家的讨论发现,如果程序在还没有删除之前,程序进程被用户强行杀掉(亦或程序crash),那么删除动作就不会发生了,临时文件就会留下成为永久文件那么如何解决这类问题呢?
方法一:
大家讨论之后决定在程序进入创建临时文件时,检查存在的废旧临时文件,并且删除它们逻辑如下:

1)检查过时临时文件; 2)删除过时临时文件 ; 3)创建临时文件; 4)使用文件; 5)删除文件。

这样的程序逻辑看上去更严谨一点,当然,也解决了遇到的问题。


那么有没有其他办法呢?
方法二:
我们可以通过去除文件的连接,来使得系统自动删除文件数据。需要我们的程序员对我们的操作系统有一定的了解,了解系统是如何去管理我们创建的文件(见文中附加内容)。


那么对于连接数为0的文件,系统kernel将会删除其所有数据~
所以,我们可以将创建的临时文件的连接数设置为0,如此一来就不必担心临时文件会不小心遗留下来~
下面是一段示例代码:

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <fcntl.h>

  5. using namespace std;

  6. int main(int argc, char *argv[])
  7. {

  8.     char *file = "/tmp/rc.bak"; //temp file to be written

  9.     //open/create file
  10.     int fd = open(file, O_RDWR | O_CREAT | O_TRUNC);
  11.     if(fd < 0)
  12.     {
  13.         cout<<"Open file failed!"<<endl;
  14.     }

  15.     //unlink file
  16.     int code = unlink(file);
  17.     if(code < 0)
  18.     {
  19.         cout<<"Unlink file failed!"<<endl;
  20.     }

  21.     //write something...
  22.     cout<<"Do other thing...."<<endl;
  23.     ssize_t n = write(fd, "abcdef",6);
  24.     sleep(3);

  25.     //read from the temp file
  26.     lseek(fd, 0, SEEK_SET);
  27.     char buffer[256];

  28.     ssize_t count = read(fd, buffer, 256);
  29.     buffer[count] = '\0';
  30.     cout<<buffer<<endl;

  31.     code = close(fd);
  32.     if(code < 0)
  33.     {
  34.         cout<<"Close file failed!"<<endl;
  35.     }
  36.     return 0;
  37. }
在这段代码中,主要分为以下几步:
1)创建rc.bak文件;
2)使用unlink,删除rc.bak的连接;
3)通过fd写读该临时文件;
4)关闭fd;
不管程序是自己运行结束还是被强行终止,在/tmp目录下,均不会存在该临时文件。

若注释掉21~25行,则如下图所示:


So, 
kernel will delete the content of this file (the process either closes the file or terminates).

附加


知识:
在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都会分配一个编号(索引节点号)。在Linux中,多个文件名可以指向同一索引节点,称之为硬连接。硬连接的作用本质上是允许一个文件拥有多个有效路径名,用户打开任何一个文件,其指向的数据部分均是相同。当一个文件有多个连接时,删除其中一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。

关于连接:

下图中,建立连接ma.cpp的连接another,可以看到两个文件的连接数均变为2(红色部分),此时已不能区分出哪个是原始文件(因为这两个是完全等同的连接)。

删除一个连接(删除another)后,连接数将会减1。

对于新创建的文件,连接数总是为1。



阅读(934) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~