首页 > 解决方案 > 当替换的大小与原始文件相同时,修改文件是否安全

问题描述

我想做一些类似sed -i 's/abc/def/' file 但没有临时文件的事情。在我的情况下,匹配和替换长度相同;以下是安全的:

fd = open(file, O_RDWR);
fstat(fd, &sbuf);
mm = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
i = 0;
while (i < sbuf.st_size) {
   memcpy(tmpbuf, mm + i, BUFSIZ);  // read from mem to tmpbuf (BUFSIZ at a time)
   if ((p = strstr(tmpbuf, needle))) { // match found
     memcpy(mm + i + (p - tmpbuf), replace, strlen(replace)); // strlen(replace) == strlen(needle)
   }
   i += BUFSIZ;
}
munmap(mm, sbuf.st_size);
fsync(fd);
close(fd);

(为简洁起见省略了错误处理)

另外,不知道mmap这是否会更快!

标签: cmmap

解决方案


这取决于您所说的“安全”是什么意思。与使用临时文件和rename完成后在旧文件之上的原子性不同,此操​​作没有原子性;其他进程可以看到文件处于中间的、部分修改的状态。而且商店之间没有任何订单;他们可以在看到替换的开始之前看到替换的结束,或者以任何其他可以想象的顺序看到它们,如果还使用和不使用任何内存屏障,甚至可能以不一致的顺序看到它们。mmap请注意, ; 真的没有什么特别之处mmap。你也可以做同样的事情write

如果这些都不构成您的“不安全”,那么操作是完全安全的。特别是它不会截断文件或类似的东西。


推荐阅读