Linux kernel 为什么需要openat()来避免stat和open()的两步竞争条件?

Linux kernel 为什么需要openat()来避免stat和open()的两步竞争条件?,linux-kernel,Linux Kernel,解释在 关于为什么需要openat,部分内容如下: openat()允许应用程序避免 使用open()打开目录以外的其他目录中的文件时可能会发生这种情况 当前工作目录。这些竞赛条件是由 事实上,目录前缀的某些组件被赋予了open() 可以与调用open()并行更改。假设 例如,如果文件 路径/to/xxx存在。问题在于,存在与否检查 以及文件创建步骤、路径或目标(可能是符号) 链接)可以修改为指向其他位置 我不明白为什么这场比赛是个问题。如果一个应用程序想要检查某个文件是否存在,如果是,则创建

解释在

关于为什么需要
openat
,部分内容如下:

openat()允许应用程序避免 使用open()打开目录以外的其他目录中的文件时可能会发生这种情况 当前工作目录。这些竞赛条件是由 事实上,目录前缀的某些组件被赋予了open() 可以与调用open()并行更改。假设 例如,如果文件 路径/to/xxx存在。问题在于,存在与否检查 以及文件创建步骤、路径或目标(可能是符号) 链接)可以修改为指向其他位置

我不明白为什么这场比赛是个问题。如果一个应用程序想要检查某个文件是否存在,如果是,则创建一个不同的文件,那么,当然,这是两个步骤,应用程序或者应该确保其间没有任何干扰,或者接受执行两步操作的后果。只有当对
open()
的单个调用可能导致竞争条件时,才可能需要一些其他系统调用,例如
openat()
。否则,这不是由系统调用来解决的,而是由应用程序负责处理的

我在这里不明白什么;DR
openat()
允许您锁定整个目录路径,只解析一次竞争条件,然后安全地打开与该路径相关的文件,而不必担心竞争条件

详细信息
正确的说法是,竞态条件仍然是程序预期和处理的责任,但是
openat()
函数只允许对多个文件执行一次。如果要在同一目录中打开多个文件,可以单独调用
open()
,但每次都必须预期并处理争用条件。相反,使用
openat()
,您可以首先获取父目录的文件描述符,这将阻止其他进程修改或删除该路径。现在,您可以使用
openat()
安全地打开相对于该锁定路径的多个文件,而不必担心打开绝对路径通常需要的竞争条件

其他用例
还请注意,争用条件不一定是在打开文件的程序和更改或删除路径的其他程序之间,而是在程序内的线程之间<代码>openat()在您想要使用相对路径并且处于多线程环境中时非常有用。请记住,如果您在一个线程中更改工作目录,它将更改整个进程及其线程的工作目录

因此,当您分叉多个线程时,它们可以各自为不同的目录获取一个文件描述符,并使用
openat()
和这些目录文件描述符以及它们之间的相对路径来打开文件,而不必担心其他线程对整个进程的工作目录做了什么,或者保持绝对路径的负载

此用例由
openat
手册页中的第二个注释描述:

其次,openat()允许通过应用程序维护的文件描述符实现每个线程的“当前工作目录”。(此功能也可以通过使用/proc/self/fd/dirfd的技巧获得,但效率较低

旁注

我不想深入讨论系统调用应该承担的责任,因为这会变得主观,但请注意,
openat
并不能真正解决竞争条件-当您尝试锁定父目录时,您仍然可以有一个竞争条件,这完全是您的程序负责处理的这是一个工具,可以帮助你在获得一次解决方案后防止种族状况。我认为这是一个有用且合理的机制,可以将其作为系统调用包含在操作系统中。

我的问题是:文档中的段落是否有错误,或者如果没有,我从中不理解什么。你的答案是事实上,文档我引用的,是不正确的,他们所说的,不是openat的一个很好的理由,原因实际上是不同的。这就是我想知道的。好的,谢谢。我没有引用第二部分,因为,我明白了。我只是想,这应该只是第二部分,第一部分是假的。@MarkGaleck我希望我y编辑澄清了第一个注释(这正是您的问题的重点)。即使最初的
open
调用将目录锁定,也会受到相同的竞争条件的约束,但一旦你拥有了它,你现在从那一点开始就安全了。这是
open
无法单独给你的东西-潜在的竞争条件总是存在的。我已经投票赞成这一点,但我我想你会想知道,这类问题是我为什么仍然经常访问的原因。它让我思考和学习,而不仅仅是调试别人的代码。谢谢你花时间问它。@skrrgwasme非常感谢你,我感谢你的回答。