AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 478314
Accepted
cat
cat
Asked: 2018-10-29 15:02:32 +0800 CST2018-10-29 15:02:32 +0800 CST 2018-10-29 15:02:32 +0800 CST

在不更改 inode 的情况下原子地写入文件(保留硬链接)

  • 772

X在 Unix 上安全、原子地写入文件的常规方法是:

  1. 将新文件内容写入临时文件Y。
  2. rename(2) Y至X

在两个步骤中,我们似乎除了X“就地”改变之外什么也没做。

它可以防止竞争条件和意外数据丢失(其中X被破坏但Y不完整或被破坏)。

这样做的缺点(在这种情况下)是它不会写入Xin-place 引用的 inode;rename(2)使得X引用一个新的 inode 号。

当X一个文件的链接计数> 1(显式硬链接)时,现在它不像以前那样引用相同的inode,硬链接被破坏了。

消除该缺点的明显方法是就地写入文件,但这不是原子的,可能会失败,可能导致数据丢失等。

有什么方法可以像原子一样进行rename(2)但保留硬链接?

也许将Y(临时文件)的 inode 编号更改为与 相同X,并为其X命名?一个 inode 级别的“重命名”。

这将有效地写入XwithY的新内容所引用的 inode,但不会破坏其硬链接属性,并会保留旧名称。

如果假设的 inode “重命名”是原子的,那么我认为这将是原子的并且可以防止数据丢失/竞争。

rename inode
  • 1 1 个回答
  • 898 Views

1 个回答

  • Voted
  1. Best Answer
    spectras
    2018-11-03T07:53:25+08:002018-11-03T07:53:25+08:00

    问题

    您在这里有一个(大部分)详尽的系统调用列表。

    您会注意到没有“替换此 inode 的内容”调用。修改该内容总是意味着:

    1. 打开文件以获取文件描述符。
    2. 可选 寻找所需的写入偏移量
    3. 写入文件。
    4. 可选 如果新数据较小,则截断旧数据。

    步骤 4 可以提前完成。还有一些快捷方式,例如pwrite,它直接在指定的偏移量处写入,结合步骤#2和#3,或分散写入。

    另一种方法是使用内存映射,但它会变得更糟,因为写入的每个字节都可能独立发送到底层文件(概念上就像每次写入都是 1 字节write调用)。

    → 重点是您可以拥有的最佳方案仍然是 2 个操作:一个write和一个truncate。

    无论您执行它们的顺序如何,您仍然冒着另一个进程在中间弄乱文件并最终导致文件损坏的风险。

    解决方案

    正常解决方案

    正如您所指出的,这就是为什么规范方法是创建一个新文件,您知道您是唯一的作者(您甚至可以通过组合O_TMPFILEand来保证这一点linkat),然后以原子方式将旧名称重定向到新文件。

    还有其他两种选择,但都以某种方式失败:

    强制锁定

    它允许通过设置特殊标志组合来拒绝其他进程的文件访问。听起来像是工作的工具,对吧?然而:

    • 它必须在文件系统级别启用(它是挂载时的标志)。
    • 警告:强制锁定的 Linux 实现是不可靠的。

      从 Linux 4.5 开始,强制锁定已成为可选功能。这是完全删除此功能的第一步。

    这是合乎逻辑的,因为 Unix 总是避开锁。它们容易出错,并且不可能涵盖所有边缘情况并保证没有死锁。

    咨询锁定

    它是使用fcntl系统调用设置的。但是,它只是建议性的,大多数程序都会忽略它。

    事实上,它只适用于管理多个协作进程之间共享文件的锁。

    结论

    有没有办法像 rename(2) 一样原子地做它但保留硬链接?

    不。

    索引节点是低级的,几乎是一个实现细节。很少有 API 承认它们的存在(我相信stat调用系列是唯一的)。

    无论您尝试做什么,都可能依赖于滥用 Unix 文件系统的设计,或者只是对其要求过高。

    这可能是一个XY问题吗?

    • 5

相关问题

  • 如何替换所有文件夹和文件名中的字符串[重复]

  • 如何在某个字符后截断文件名

  • 递归地从文件名中删除字符

  • Krename:如何为每个文件夹重新编号?

  • 根据其中的值批量重命名(附加)CSV 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve