gpt4 book ai didi

c - 使用 Write() 和 snprintf() 以原子方式写入文件

转载 作者:行者123 更新时间:2023-11-30 15:03:06 32 4
gpt4 key购买 nike

我希望能够以原子方式写入文件,我正在尝试使用 write() 函数,因为它似乎在大多数 linux/unix 系统中授予原子写入权限。

由于我有可变的字符串长度和多个 printf,我被告知使用 snprintf() 并将其作为参数传递给 write 函数,以便能够在读取时正确执行此操作这个函数的文档我做了如下测试实现:

int file = open("file.txt", O_CREAT | O_WRONLY);
if(file < 0)
perror("Error:");
char buf[200] = "";
int numbytes = snprintf(buf, sizeof(buf), "Example string %s" stringvariable);
write(file, buf, numbytes);

从我的测试来看,它似乎有效,但我的问题是这是否是实现它的最正确的方法,因为我正在创建一个相当大的缓冲区(我100%肯定会适合我所有的 printfs)来存储它顺便写一下。

最佳答案

  1. 不,write() 不是原子性的,即使它写入一次调用中提供的所有数据也是如此。

  2. 在所有读取器和写入器中使用建议记录锁定 ( fcntl(fd, F_SETLKW, &lock) ) 来实现原子文件更新。

    基于 fcntl() 的记录锁可在 Linux 和 BSD 上通过 NFS 工作;基于集群()的文件锁可能不会,具体取决于系统和内核版本。 (如果像某些 Web 托管服务一样禁用 NFS 锁定,则任何锁定都不会可靠。)只需使用 .l_whence = SEEK_SET, .l_start = 0, .l_len 初始化 struct farm = 0 引用整个文件。

  3. 使用asprintf()打印到动态分配的缓冲区:

     char *buffer = NULL;
    int length;

    length = asprintf(&buffer, ...);
    if (length == -1) {
    /* Out of memory */
    }

    /* ... Have buffer and length ... */

    free(buffer);
  4. 添加锁定后,请将 write() 包装在循环中:

     {
    const char *p = (const char *)buffer;
    const char *const q = (const char *)buffer + length;
    ssize_t n;

    while (p < q) {

    n = write(fd, p, (size_t)(q - p));
    if (n > 0)
    p += n;
    else
    if (n != -1) {
    /* Write error / kernel bug! */
    } else
    if (errno != EINTR) {
    /* Error! Details in errno */
    }
    }
    }

    尽管有一些本地文件系统保证 write() 不会返回短计数,除非您耗尽存储空间,但并非所有系统都会这样做;尤其是那些联网的。使用上面的循环可以让你的程序甚至在这样的文件系统上运行。在我看来,为了可靠和健壮的操作而添加的代码并不多。

  5. 在 Linux 中,您可以使用 a write lease位于文件上以排除暂时打开该文件的任何其他进程。

    本质上,您无法阻止文件打开,但您可以将其延迟最多 /proc/sys/fs/lease-break-time 秒,通常为 45 秒。仅当没有其他进程打开该文件时才授予租约,并且如果任何其他进程尝试打开该文件,租约所有者会收到信号。 (如果租约所有者没有释放租约,例如通过关闭文件,内核将在租约中断时间结束后自动中断租约。)

    不幸的是,这些仅适用于 Linux,并且仅适用于本地文件,因此它们的用途有限。

  6. 如果读者不保持文件打开,而是在每次读取文件时打开、读取和关闭它,则可以编写完整的替换文件(必须位于同一文件系统上;我建议使用锁-的子目录),并将其硬链接(hard link)到旧文件上。

    所有读者都将看到旧文件或新文件,但那些保持文件打开状态的读者将永远不会看到任何更改。

关于c - 使用 Write() 和 snprintf() 以原子方式写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40834800/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com