最近,在现场调试程序的同事反馈回了一个问题:目的文件已不在原目录,程序还会继续执行写文件操作。我们了解了一下,具体的情况是这样的:某软件(运行在Linux下)有一个功能是在配置好的某个目录中生成文件,在文件生成的过程中,现场同事将已经生成的文件移动到了另外一个目录中;过了一段时间后发现,程序继续向移动之后的文件中写入内容,导致该文件不断增大。
为了还原现场问题,我们编写了以下程序:
/**********************************************************************
* 版权所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名称:WriteFileNonStop.c
* 文件标识:无
* 内容摘要:不停地写文件
* 其它说明:无
* 当前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20150917
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
// 数据类型重定义
typedef signed int INT32;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef unsigned short int UINT16;
typedef unsigned int UINT32;
// 函数声明
void Sleep(UINT32 iCountMs);
void WriteFileNonStop(void);
INT32 main();
/**********************************************************************
* 功能描述:主函数
* 输入参数:无
* 输出参数:无
* 返 回 值:无
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
* -------------------------------------------------------------------
* 20150917 V1.0 Zhou Zhaoxiong 创建
*********************************************************************/
INT32 main()
{
WriteFileNonStop(); // 写文件
return 0; // main函数返回0
}
/**********************************************************************
* 功能描述: 把内容写到本地文件中
* 输入参数: pszContentLine-一条文件记录
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期 版本号 修改人 修改内容
* ----------------------------------------------------------------------
* 20150917 V1.0 Zhou Zhaoxiong 创建
************************************************************************/
void WriteFileNonStop(void)
{
FILE *fp = NULL;
INT8 szLocalFile[500] = {0};
INT8 szCurDate[20] = {0};
INT8 szContentBuf[200] = {0};
snprintf(szLocalFile, sizeof(szLocalFile)-1, "%s/zhouzhaoxiong/zzx/WriteFileNonStop/File/File.txt", getenv("HOME"));
fp = fopen(szLocalFile, "a+");
if (fp == NULL)
{
printf("WriteFileNonStop: open local file failed, file=%s\n", szLocalFile);
return;
}
while (1) // 不停地写文件
{
strcpy(szContentBuf, "hello, world!\n");
printf("WriteFileNonStop: LocalFile=%s, ContentBuf=%s", szLocalFile, szContentBuf);
fputs(szContentBuf, fp);
fflush(fp);
Sleep(10 * 1000); // 每10s写一次
}
fclose(fp);
fp = NULL;
return;
}
/**********************************************************************
* 功能描述: 程序休眠
* 输入参数: iCountMs-休眠时间(单位:ms)
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期 版本号 修改人 修改内容
* ------------------------------------------------------------------
* 20150917 V1.0 Zhou Zhaoxiong 创建
********************************************************************/
void Sleep(UINT32 iCountMs)
{
struct timeval t_timeout = {0};
if (iCountMs < 1000)
{
t_timeout.tv_sec = 0;
t_timeout.tv_usec = iCountMs * 1000;
}
else
{
t_timeout.tv_sec = iCountMs / 1000;
t_timeout.tv_usec = (iCountMs % 1000) * 1000;
}
select(0, NULL, NULL, NULL, &t_timeout); // 调用select函数阻塞程序
}
该程序命名为“WriteFileNonStop.c”,其实现的功能是:每隔10秒向当前用户的“zhouzhaoxiong/zzx/WriteFileNonStop/File/”目录下的“File.txt”文件中写入“hello, world!”。我们之所以要用一个“while”循环来不断地写文件,就是为了查看在我们将文件移走或删除之后,程序会怎么处理。
利用“gcc -g -o WriteFileNonStop WriteFileNonStop.c”命令编译程序之后,生成了“WriteFileNonStop”文件。接下来,我们要复现现场的问题。
1.执行“WriteFileNonStop”命令,可以看到程序运行正常,并且在“zhouzhaoxiong/zzx/WriteFileNonStop/File/”目录下有文件生成。
程序运行情况:
~/zhouzhaoxiong/zzx/WriteFileNonStop> gcc -g -o WriteFileNonStop WriteFileNonStop.c
~/zhouzhaoxiong/zzx/WriteFileNonStop> WriteFileNonStop
WriteFileNonStop: LocalFile=/home/zxin10/zhouzhaoxiong/zzx/WriteFileNonStop/File/File.txt, ContentBuf=hello, world!
WriteFileNonStop: LocalFile=/home/zxin10/zhouzhaoxiong/zzx/WriteFileNonStop/File/File.txt, ContentBuf=hello, world!
WriteFileNonStop: LocalFile=/home/zxin10/zhouzhaoxiong/zzx/WriteFileNonStop/File/File.txt, ContentBuf=hello, world!
WriteFileNonStop: LocalFile=/home/zxin10/zhouzhaoxiong/zzx/WriteFileNonStop/File/File.txt, ContentBuf=hello, world!
文件生成情况:
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> ll
-rw-rw-rw- 1 zhou dba 42 Sep 17 16:30 File.txt
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> tail -f File.txt
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
2.我们将生成的“File.txt”文件移动到其它目录中,可以看到程序继续运行,并且文件中继续有内容生成。
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> mv File.txt ..
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> ll
total 0
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> cd ..
~/zhouzhaoxiong/zzx/WriteFileNonStop> ll
drwx------ 2 zhou dba 4096 Sep 17 16:34 File
-rw-rw-rw- 1 zhou dba 392 Sep 17 16:34 File.txt
-rwxrwxrwx 1 zhou dba 14897 Sep 17 16:29 WriteFileNonStop
-rw------- 1 zhou dba 3434 Sep 17 16:29 WriteFileNonStop.c
~/zhouzhaoxiong/zzx/WriteFileNonStop> tail -f File.txt
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
hello, world!
3.我们将“File.txt”文件删除掉,可以看到程序继续运行,但没有文件生成。
~/zhouzhaoxiong/zzx/WriteFileNonStop> rm File.txt
~/zhouzhaoxiong/zzx/WriteFileNonStop> ll
drwx------ 2 zhou dba 4096 Sep 17 16:34 File
-rwxrwxrwx 1 zhou dba 14897 Sep 17 16:29 WriteFileNonStop
-rw------- 1 zhou dba 3434 Sep 17 16:29 WriteFileNonStop.c
~/zhouzhaoxiong/zzx/WriteFileNonStop> cd File
~/zhouzhaoxiong/zzx/WriteFileNonStop/File> ll
total 0
4.为了对程序进行更全面的验证,在写文件的过程中,我们将文件移动到另外一个Linux用户下(即当前用户下的程序无法访问另外一个用户),发现程序依然继续运行,但没有文件生成。
通过以上测试验证的结果,我们得出了以下的结论:
第一,C语言中的写文件操作是通过文件句柄来向对应的文件中写入内容的,如果程序有访问文件句柄的权限,那么不管文件放在哪个目录下,都能够成功写入。
第二,在写文件的过程中,如果将文件删除,或者是放到了程序无权访问的目录下,那么程序也不会报错,而是继续执行。因此,对于需要写文件的软件来说,一定要确保相关目录下的文件不会被误移动或误删除。
欢迎大家关注并支持本人新书《C程序员从校园到职场》。