mkdir仍然是原子的吗?(安装在SAN上的Windows 7文件系统)

mkdir仍然是原子的吗?(安装在SAN上的Windows 7文件系统),windows,mkdir,atomicity,san,Windows,Mkdir,Atomicity,San,我们有一些通过基于目录的队列进行通信的旧应用程序。队列中的每个项目都是一个文件,并且有一个头文件,用于维护队列中项目的有序文件名列表 当然,这段旧代码需要在推送和弹出项目时锁定队列。它所做的是创建一个锁子目录,假设mkdir()是一个原子操作——如果多个进程试图创建一个目录,那么其中只有一个会成功 我的一位同事一直在努力解决一个模糊的问题,他认为原因是,当进程在不同的机器上运行时,以及当所讨论的文件系统安装在SAN上时,这种锁定不再起作用 有没有可能他是对的 我知道这是一个很老的问题,但我希望有

我们有一些通过基于目录的队列进行通信的旧应用程序。队列中的每个项目都是一个文件,并且有一个头文件,用于维护队列中项目的有序文件名列表

当然,这段旧代码需要在推送和弹出项目时锁定队列。它所做的是创建一个锁子目录,假设mkdir()是一个原子操作——如果多个进程试图创建一个目录,那么其中只有一个会成功

我的一位同事一直在努力解决一个模糊的问题,他认为原因是,当进程在不同的机器上运行时,以及当所讨论的文件系统安装在SAN上时,这种锁定不再起作用


有没有可能他是对的

我知道这是一个很老的问题,但我希望有人能对此感兴趣

使用PowerShell创建一个共享文件夹用作互斥体时,我也得到了令人困惑的结果,所以我创建了一个测试脚本

function New-FolderMutex {
    try {
        New-Item -ItemType directory -Path .\TheMutex -ErrorAction Stop > $null
        $true
    } catch {
        $false
    }
}

function Remove-FolderMutex {
    Remove-Item -Path .\TheMutex
}

1..100 | % {
    if (New-FolderMutex) {
        Write-Host "Inside loop $_"
        Remove-FolderMutex
    }
}
此脚本在当前目录位于网络共享中时运行

当我在两个单独的PowerShell控制台中同时运行此脚本时,从错误消息中可以清楚地看出,该方法注定失败。调用移除项会产生许多不同的错误,即使它仅由创建文件夹的进程调用。似乎在幕后有一大堆非原子步骤正在发生

当然,OP询问的是
mkdir
(可能是系统调用),我的示例使用的是更高级别的PowerShell cmdlet,但我希望这会引起一些兴趣

两个过程之一的输出示例(为简洁起见编辑)


在文件服务器上创建和/或删除目录时,我遇到了一些奇怪的行为(自从移动到Windows7/2008R2之后)。我还不能确定细节,但如果你的同事观察结果是正确的,我也不会感到惊讶。建议:更改代码,这样当它以这种方式创建目录时,它还会添加一个随机生成(但可识别)名称的文件。如果它后来在一个目录中看到两个这样的文件,那么您已经确认锁定不起作用。我不确定这是否会起作用。看起来,允许两个mkdir发生的低级优化同样可能会让一个程序看不到另一个程序已经创建了一个文件,直到为时已晚。我不是说这是一种解决方案,只是一种确认您认为可能发生的事情实际上正在发生的可能方式。虽然它不能证明它没有发生,但它可以证明它确实发生了!另一种可能是在同一共享上创建一个全局日志文件(具有适当的显式锁定语义),记录目录的创建和删除。
Inside loop 30
Inside loop 31
Inside loop 32
Inside loop 33
Inside loop 34
Remove-Item : Access to the path 'H:\My Documents\PowerShell\MutexFolder\TheMutex' is denied.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+     Remove-Item -Path .\TheMutex
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (H:\My Documents...Folder\TheMutex:String) [Remove-Item], UnauthorizedAccessException
    + FullyQualifiedErrorId : RemoveItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.RemoveItemCommand

Inside loop 39
Remove-Item : H:\My Documents\PowerShell\MutexFolder\TheMutex is a NTFS junction point. Use the Force parameter to delete or modify.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+     Remove-Item -Path .\TheMutex
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (H:\My Documents...Folder\TheMutex:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : DirectoryNotEmpty,Microsoft.PowerShell.Commands.RemoveItemCommand

Inside loop 42
Remove-Item : Could not find a part of the path 'H:\My Documents\PowerShell\MutexFolder\TheMutex'.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+     Remove-Item -Path .\TheMutex
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (H:\My Documents...Folder\TheMutex:String) [Remove-Item], DirectoryNotFoundException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand

Inside loop 44
Inside loop 45