mkstemp() 是如何工作的?
How mkstemp() actually works?
我对mkstemp()
函数的工作过程感到困惑。
在mkstemp
函数的man
页面中,据说该函数生成唯一名称并使用该名称创建文件。
我认为有可能当 mkstemp()
在目录中检查该文件名并在实际创建该文件之前发现它是唯一的时,另一个程序可以创建具有完全相同名称的文件(尽管有可能非常低,但理论上是可能的)。尽管它将无法创建文件,因为它使用 O_EXCL
标志。因此,它必须再次检查新文件名并创建它。
这是 mkstemp()
工作的实际过程吗?
因此,我认为检查文件名和实际创建文件这两个过程都不是自动完成的。 (我可能错了)
使用POSIX
系统
How mkstemp() actually works?
源代码是算法的文字描述。进行一项实施并检查它。
https://github.com/lattera/glibc/blob/master/misc/mkstemp.c -> https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c 检查输入
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L229 获取一些随机数据
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L241 repeat for https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L211指定的尝试次数
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L245 用随机数
XXXXXX
填充
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L261 用
O_CREAT | O_EXCL
打开文件
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L293如果文件打开return,如果未知错误return,如果文件存在,重复
所以没有“检查”,文件从一开始就用 O_CREAT | O_EXCL
打开,所以创建和检查是一起完成的。有关 open
标志的说明,请参阅 https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html。
(although chances are very low, but it is possible theoretically)
不,这是不可能的(即使在理论上),因为 mkstemp()
用于创建文件的 open()
系统调用保证没有两个进程可以使用 [=12= 创建相同的文件] 和 O_EXCL
同时。当内核创建文件时,目录 inode 被锁定(因此,不允许同时在该目录中创建任何其他文件),这保证两个 open()
s 将被序列化(第一个,或者其他,但不是同时)这意味着当第二个进程有机会创建文件时, open()
调用失败,因为该文件已经被另一个进程创建。为了尽量减少这种情况,该函数通常使用进程的 pid 作为名称的一部分,因此两个进程不能同时生成相同的文件名,因为它们具有不同的进程 ID)mkstemp()
将重试系统调用可能是一个不同的名字,或者只是失败。
我对mkstemp()
函数的工作过程感到困惑。
在mkstemp
函数的man
页面中,据说该函数生成唯一名称并使用该名称创建文件。
我认为有可能当 mkstemp()
在目录中检查该文件名并在实际创建该文件之前发现它是唯一的时,另一个程序可以创建具有完全相同名称的文件(尽管有可能非常低,但理论上是可能的)。尽管它将无法创建文件,因为它使用 O_EXCL
标志。因此,它必须再次检查新文件名并创建它。
这是 mkstemp()
工作的实际过程吗?
因此,我认为检查文件名和实际创建文件这两个过程都不是自动完成的。 (我可能错了)
使用POSIX
系统
How mkstemp() actually works?
源代码是算法的文字描述。进行一项实施并检查它。
https://github.com/lattera/glibc/blob/master/misc/mkstemp.c -> https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c 检查输入
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L229 获取一些随机数据
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L241 repeat for https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L211指定的尝试次数
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L245 用随机数
XXXXXX
填充 - https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L261 用
O_CREAT | O_EXCL
打开文件- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L293如果文件打开return,如果未知错误return,如果文件存在,重复
- https://github.com/lattera/glibc/blob/master/sysdeps/posix/tempname.c#L245 用随机数
所以没有“检查”,文件从一开始就用 O_CREAT | O_EXCL
打开,所以创建和检查是一起完成的。有关 open
标志的说明,请参阅 https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html。
(although chances are very low, but it is possible theoretically)
不,这是不可能的(即使在理论上),因为 mkstemp()
用于创建文件的 open()
系统调用保证没有两个进程可以使用 [=12= 创建相同的文件] 和 O_EXCL
同时。当内核创建文件时,目录 inode 被锁定(因此,不允许同时在该目录中创建任何其他文件),这保证两个 open()
s 将被序列化(第一个,或者其他,但不是同时)这意味着当第二个进程有机会创建文件时, open()
调用失败,因为该文件已经被另一个进程创建。为了尽量减少这种情况,该函数通常使用进程的 pid 作为名称的一部分,因此两个进程不能同时生成相同的文件名,因为它们具有不同的进程 ID)mkstemp()
将重试系统调用可能是一个不同的名字,或者只是失败。