检查文件是不是被进程文件句柄锁定

Posted

技术标签:

【中文标题】检查文件是不是被进程文件句柄锁定【英文标题】:Check if file is locked by a process filehandle检查文件是否被进程文件句柄锁定 【发布时间】:2016-04-14 14:46:20 【问题描述】:

鉴于我有一个所有进程的所有文件句柄的列表,我如何找出这些句柄中的哪些实际上正在锁定文件?

据我了解,我可以简单地尝试打开文件并尝试获取所有权限,如果出现问题,我会知道它已被锁定。但这听起来效率极低。我的意思是我已经有了句柄没有办法检查句柄有哪些权限吗?

我希望看到一个适用于 Windows XP 及更高版本的解决方案。

我已经搜索了GetFileInformationByHandleEx 函数,但我找不到任何有关访问权限的信息。 :/

编辑: 我不需要有关文件锁定的实时信息。我计划处理的文件要么被锁定,直到某些应用程序关闭,要么根本不被锁定。

【问题讨论】:

请求宽恕胜过许可 您可以通过尝试写入句柄来读取文件的“锁定性”,因为读/写只能由句柄的所有者进行。 没有办法做到这一点。任何类型的 IsFileLocked() 函数都无法在多任务操作系统上可靠地工作。它返回的值会立即失效,并且不能保证在您尝试访问文件时它仍然处于解锁状态。您可以通过访问文件来发现,这是原子的。它不是低效的,只有当它被锁定时你会做什么。如果假设的 IsFileLocked() 函数返回 TRUE,这与您所做的完全相同。通过防止其他进程在您打开文件时锁定文件来避免所有这些。 @Joel:当您打开文件时,您指定共享模式(以及其他)。您可以打开一个文件进行写入,并允许其他人读取/写入同一文件。处理所有权与此无关。另外,除了读写之外,文件还有其他操作,例如删除它,或查询信息。 我不需要文件锁的实时信息。我计划处理的文件要么被锁定,直到某些应用程序关闭,要么根本不被锁定。 【参考方案1】:

此问题与Win32 files locked for reading: how to find out who's locking them 重复。

此外,Hans Passant 的评论是正确的:查询任何 Win32 文件的锁定状态都会提供陈旧的信息。忽略此警告将导致难以发现的错误。

如果您控制所有您认为会访问文件的代码位,最好使用named pipe 进行进程间通信,而不是查询锁定的文件。

【讨论】:

不是真正的重复。我不仅对读锁感兴趣。我对任何类型的锁都感兴趣。删除、写入、读取以及仅锁定文件中特定区域的锁定。再一次,这些信息有多陈旧并不重要。而且我不打算对流程进行逆向工程以注入管道功能等等。 @Forivin:那些不是锁,这可能是造成混乱的原因。共享违规源于一个独立的概念:共享标志。因此,如果一个文件被打开并允许读取它,任何其他进程(如果其他检查通过)将能够获得对该文件的读取访问权限。但据我所知,这与锁定不同。因此,您需要弄清楚您的术语。 @Forivin 还要比较ERROR_SHARING_VIOLATIONERROR_LOCK_VIOLATION 错误代码(winerror.h)。【参考方案2】:

您可以使用NtQueryObject API 获取有关句柄的信息,包括以下内容:

ULONG Attributes;
ACCESS_MASK GrantedAccess;

或者您可以使用FileModeInformationFileAccessInformationFileInformationClass 参数值访问相同的信息。

【讨论】:

我创建了很多测试文件,并使用读/写/删除和写锁定访问的每种组合对它们创建了句柄。然后在另一个使用 SeDebugPrivilege 等提升权限运行的应用程序中。我检查了 GrantedAccess、属性、标志等。结果如下:i.snag.gy/uHOMr.jpg 我认为可以肯定地说这些都不包含任何有关锁定状态的有用信息。 这只有在你继承了一个句柄时才有意义。否则,您自己的进程就是打开它的进程(好吧,KM 也可能有)。并且授予的访问权限已经绑定到该对象。但共享、锁定和初始访问是相关但独立的概念。

以上是关于检查文件是不是被进程文件句柄锁定的主要内容,如果未能解决你的问题,请参考以下文章

关闭其它进程占用的文件句柄

lsof恢复进程打开的文件

Perl:当子/管道的文件句柄被别名时,关闭子进程失败

文件句柄文件描述符与进程和多线程的那些事

Linux 系统级开启文件句柄 调优

查找当前打开的文件句柄数(不是 lsof)