繁体   English   中英

在Linux上将fwrite用作原子过程

[英]using fwrite as an atomic process on Linux

我正在Linux环境上开发C代码。 我使用fwrite将一些数据写入某些文件。 该程序将在经常断电的环境中运行(每天至少一次)。 因此,我希望fwrite确保在写入数据时断电不会更新文件。 它仅应在fwrite完成其工作时保存文件。 我如何使用fwrite仅在完成写入过程后才影响文件?

编辑:我用fopen和wb来丢弃文件中的先前信息,并写入一个新文件,例如

FILE *rtng_p;
rtng_p = fopen("/etc/routing_table", "wb");
fwrite(&user_list, sizeof(struct routing), 40, rtng_p);

这是一个很小的数据,长几个字节

首先将文件写入同一文件系统上的临时路径,例如/etc/routing_table.tmp 然后,只需将副本重命名为原始文件即可。 重命名保证是原子的。

因此,调用顺序将为fopenfwritefcloserename

除了David Schwartz回答中给出的顺序外,您还可以在诸如 flock(2) syscall的情况下使用咨询锁(或者可以使用F_SETLK ....的lockf(3)fcntl(2) )。

那意味着要添加

 FILE * fil = fopen("/etc/routing_table.tmp", "wb");

线

 if (!fil) 
   { perror("/etc/routing_table.tmp"); exit(EXIT_FAILURE); };
 if (flock(fileno(fil), LOCK_EX)) 
   { perror("flock LOCK_EX"); exit(EXIT_FAILURE); };

最后,你会

 if (fflush(fil)) /* flush the file before unlocking it!!*/
   { perror("fflush"); exit(EXIT_FAILURE); };
 if (flock(fileno(fil), LOCK_UN))
   { perror("flock LOCK_UN"); exit(EXIT_FAILURE); };
 if (fclose (fil))
   { perror("fclose"); exit(EXIT_FAILURE); };;
 if (rename("/etc/routing_table.tmp", "/etc/routing_table"))
   { perror("rename"); exit(EXIT_FAILURE); };

使用这种建议性锁定将确保即使程序的两个进程正在运行,也只有一个进程可以写入文件。

但这可能是过度杀伤力。

顺便说一句,您似乎在/etc/写入二进制数据。 我认为这违反了习惯或惯例(请参阅Linux Filesystem HierarchyLinux Standard Base )。 我希望/etc下的文件是文本文件。 也许您想要将文件放在/var/lib

另请参见在线高级Linux编程书籍。

在UNIX / Linux社区中,关于open/write/close/rename模式(如David Schwartz的答案中所述 )是否真正被保证是原子的一直存在很大争议。 请注意,此对话是关于write而不是fwrite

EXT4文件系统的主要作者并不认为应该根据POSIX对其进行保证,并且文件系统的早期版本并未将其视为原子的。 最终,他屈服了,并使这组操作成为EXT4的默认行为。 但是,有人声称用户程序实际上应该在执行open/write/fsync/close/rename

没有fsync ,其他文件系统可能无法保证原子性,并且如果EXT4用noauto_da_alloc挂载,那么该保证也会在那里丢失。 因此,如果您想真正安全,则应在close之后在rename之前添加fsync 我没有用fwrite尝试过,如果您使用fflush可能会起作用。

有关更多信息,请参见https://www.kernel.org/doc/Documentation/filesystems/ext4.txt上auto_da_alloc部分。 另请参阅EXT4主要作者写的文章: http : //thunk.org/tytso/blog/2009/03/12/delayed-allocation-and-the-zero-length-file-problem/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM