发生了什么很简单:你是清空文件。
为什么它充满了^@
s,那么,你问?那么,从实际意义上说,事实并非如此。它不包含那些怪异的字符。它有一个“洞”。
被写入文件的程序编写与O_WRONLY
(或者O_RDWR
),但不O_APPEND
打开的文件。当你用cp /dev/null filename
或: > filename
或其他类似的命令清空文件时,该程序已经将文件写入了65536字节。
现在程序进入write
数据的另一块(比如说,4096个或8192字节)。数据将写在哪里?答案是:“在底层文件描述符上的当前查找偏移量”。如果使用的程序O_APPEND
write
将实际上在进行“寻求当前文件结束,即文件的当前长度”的lseek
调用之后。当截断文件“当前文件结束”将变为零(文件变为空)时,搜索会将write
偏移量移动到位置0,并且写入将会到达那里。但该程序没有使用O_APPEND
,所以没有预定义write
“重新定位”操作,并且数据字节被写入当前偏移量(这又是我们声称的65536以上)。
您现在有一个文件,该文件在字节偏移没有数据 0到65535包容性,其次是一些数据的字节偏移65536到73727(假设write
写入8192个字节)。这个“缺失”的数据是文件中的“漏洞”。当其他程序读取文件时,操作系统假装有是有数据:全零字节数据。
如果执行write
操作的程序不在块边界上执行它们,OS实际上会分配一些额外的数据(以适合写入整个块)并将其归零。那些零字节不是“洞”的一部分(它们是文件中真正的零字节),而是普通程序,它们不会在“绿野仙踪”中隐藏幕后,“洞”零字节和“非“零”字节是难以区分的。
你需要做的是修改程序以使用O_APPEND
,或者使用像syslog
这样的库例程,它们知道如何配合对数旋转操作,或者两者兼而有之。
[编辑补充:不知道为什么这个突然出现在头版,我回答了2011年的一个问题...]
echo“”> filename? – 2011-12-15 10:02:47
当你真正看到“^ @^@^@^@`时,为什么要写'@@@@`? – glglgl 2011-12-15 10:41:17
@gigigi修正后 – 2011-12-15 11:00:06