网上有很多人说您可以使用> filename
或truncate -s0 filename
在文件开始使用时截断文件
我知道每次进程在文件中写入数据时,该进程都会使用偏移量来写入文件,并使用类似的脚本进行测试。
#!/usr/bin/env python
import os, time
with open("passwd","w") as f: #copy of passwd file in my current directory
f.seek(0)
for x in xrange(1,1000):
f.write("hello world \n" + time.ctime() + "\n")
f.flush()
time.sleep(2)
每次我的脚本进行系统调用时,/proc/pid_number/fdinfo/3 pos
都会更改字段的偏移量,但是当我尝试使用上面列出的方法截断文件时,在我的文件中,^@
当我使用vim
或更少-u
的文件打开文件时,会看到很多这样的字符,并且文件类型是从更改ASCII text
为data
,当我使用ls -l filename
尺寸不变时
因此,当截断文件时,文件的偏移量不会返回,我正在inCentos 7
和in中对此进行测试Redhat 5
,因此我可以知道在进程使用文件时更改文件的大小不会释放空间并使我的文件变脏。文件。
所以我的问题是,如果我的进程中有一个打开的文件,pos 1000
而我确实有truncate -s0 filename
,则如果截断有效,那么下一个进程中会发生什么?
strace truncate -s0 passwd
open("passwd", O_WRONLY|O_CREAT|O_NONBLOCK, 0666) = 3
ftruncate(3, 0) = 0
close(3) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
ls -l passwd
-rw-rw-r--. 1 user91 users 13832 Feb 23 17:16 passwd
如您所见,我的文件没有被截断
如果我以附加代码打开附加模式,则不会发生此问题。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
int main(){
int range = 1000;
int x; x = open("passwd", O_WRONLY|O_CREAT|O_APPEND);
int i = 0;
for( i = 0; i <= range; range++)
write(x,"hello world\n",12);
sleep(2);
}
请注意,尽管系统调用称为truncate,但实际上最好将其解释为“使我的文件报告这么多字节的大小”。根据系统调用手册页:
truncate()和ftruncate()函数使由path命名或由fd引用的常规文件被截断为恰好长度字节的大小。
如果该文件以前大于此大小,则多余的数据将丢失。如果该文件先前较短,则将其扩展,并且扩展部分读取为空字节('\ 0')。
因此,可以截断一个文件并使它更大而不是更小。
所以我的问题是,如果我的进程在pos 1000中有一个打开的文件,并且我确实截断了-s0文件名,如果截断有效,那么下一个进程中写的是什么?
当您从大于文件本身的位置写入文件时,文件末尾与新写入之间的数据将变为空字节,并且这两点之间的文件数据被称为sparse。
确实,您可以执行以下操作并产生相同的效果。
import os, sys
f = open('data.txt','w')
f.seek(1048576)
f.write('a')
f.flush()
f.close()
您还提到以附加模式打开可避免此行为。这是正确的,因为在这种情况下您正在指示内核“每次都写入文件的实际末尾”。如果截断,则文件末尾确实会更改。另外,您不能重新定位文件指针。
这是一个示例程序,演示了文件,偏移量和已被截断的文件中的数据将发生什么情况。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <err.h>
#define FPATH "/tmp/data.txt"
#define FSIZE 65536
int main() {
int a,b;
char buf[FSIZE];
char byte;
struct stat st;
memset(buf, 'A', FSIZE);
a = open(FPATH, O_WRONLY|O_CREAT);
b = open(FPATH, O_RDONLY);
if (a < 0 || b < 0)
errx(EXIT_FAILURE, "Could not open file");
printf("Writing %d * 'A' into file\n", FSIZE);
/* Write some bytes */
if(write(a, buf, FSIZE) != FSIZE)
errx(EXIT_FAILURE, "Couldn't write complete size out");
/* Seek to a new position in the file */
lseek(b, FSIZE/2, SEEK_SET);
printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
stat(FPATH, &st);
printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);
/* OK -- now, read the byte at the position */
if (read(b, &byte, 1) < 0)
err(EXIT_FAILURE, "Could not read file");
printf("Character at current position of handle 'b': '%c'\n", byte);
/* Truncate the file in the 'a' handle */
printf("Performing truncate...\n");
if (ftruncate(a, 0) < 0)
err(EXIT_FAILURE, "Cannot truncate file");
printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
stat(FPATH, &st);
printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);
printf("Writing one byte via handle 'a'\n");
if (write(a, buf, 1) < 0)
err(EXIT_FAILURE, "Cannot perform second write");
printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
stat(FPATH, &st);
printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);
if (read(b, &byte, 1) < 0)
err(EXIT_FAILURE, "Could not read file");
printf("Character at current position of handle 'b': '%c'\n", byte);
close(a);
close(b);
exit(0);
}
结果为以下输出;
Writing 65536 * 'A' into file
Current position of handle 'a': 65536
Current position of handle 'b': 32768
Reported size on filesystem of /tmp/data.txt: 65536
Character at current position of handle 'b': 'A'
Performing truncate...
Current position of handle 'a': 65536
Current position of handle 'b': 32769
Reported size on filesystem of /tmp/data.txt: 0
Writing one byte via handle 'a'
Current position of handle 'a': 65537
Current position of handle 'b': 32769
Reported size on filesystem of /tmp/data.txt: 65537
Character at current position of handle 'b': ''
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句