如何检查文件是否已被C中的其他进程打开?

win*_*lin 10 c windows file

我看到标准C无法判断文件是否已在另一个进程中打开.所以答案应该包含每个平台的几个例子.我需要检查Visual C++/Windows.

Hal*_*Hal 9

windows:尝试以独占模式打开文件.如果它工作,没有其他人打开该文件,将无法打开该文件

HANDLE fh;
fh = CreateFile(filename, GENERIC_READ, 0 /* no sharing! exclusive */, NULL, OPEN_EXISTING, 0, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
   // the only open file to filename should be fh.
   // do something
   CloseHande(fh);
}
Run Code Online (Sandbox Code Playgroud)

MS说:dwShareMode

对象的共享模式,可以是读取,写入,同时,删除,所有这些或无(参见下表).

如果此参数为零并且CreateFile成功,则无法共享该对象,并且在关闭句柄之前无法再次打开该对象.

您不能请求与具有打开句柄的打开请求中指定的访问模式冲突的共享模式,因为这会导致以下共享冲突:ERROR_SHARING_VIOLATION.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

扩展:如何删除没有人打开读/写的(不是只读)文件文件系统?

访问权限FILE_READ_ATTRIBUTES,而不是DELETE.DELETE可能会导致smb共享问题(对于MS Windows服务器) - CreateFile将以仍然打开的FileHandle/Device/Mup:xxx文件名离开 - 为什么以及这个Mup是什么.访问权限不会发生FILE_READ_ATTRIBUTES使用FILE_FLAG_OPEN_REPARSE_POINT删除文件名.否则,您将删除符号链接的目标 - 这通常不是您想要的

HANDLE fh;
fh = CreateFile(filename,  FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE /* no RW sharing! */, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_DELETE_ON_CLOSE, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
    DeleteFile(filename); /* looks stupid?
                          * but FILE_FLAG_DELETE_ON_CLOSE will not work on some smb shares (e.g. samba)!
                          * FILE_SHARE_DELETE should allow this DeleteFile() and so the problem could be solved by additional DeleteFile()
                          */
    CloseHande(fh); /* a file, which no one has currently opened for RW is delete NOW */

} 
Run Code Online (Sandbox Code Playgroud)

如何处理打开的文件?如果文件已打开且您可以进行取消链接,则会留下一个文件,后续打开将导致ACCESS_DENIED.如果你有一个temoprary文件夹,那么重命名(filename,tempdir/filename.delete)和删除tempdir/filename.delete是一个好主意.


Han*_*ant 8

除非另一个进程明确禁止访问该文件,否则无法判断.在MSVC中,您可以使用_fsopen(),指定_SH_DENYRDshflag参数.对于是否打开未被锁定的文件感兴趣的概念在多任务操作系统上存在严重缺陷.它可能会在您发现它不是之后打开一微秒.这也是Windows没有IsFileLocked()函数的原因.

如果需要对文件进行同步访问,则需要使用命名的互斥锁添加它,使用CreateMutex().


Car*_*icz 5

获取 open_files 信息很困难,就像拔牙一样,如果您没有立即需要它,您不应该仅仅为了它而要求“每个平台的几个示例”。当然只是我的意见。

Linux 和许多 Unix 系统都有一个名为 的系统实用程序lsof,它可以查找打开的文件句柄等内容。它这样做的方式是通过访问/dev/kmem,它是一个伪文件,包含“活动”内核内存的副本,即操作系统内核的工作存储。当然,那里有打开文件的表格,并且内存结构是开源的并且有文档记录,因此 lsof 进入那里,查找信息并为用户格式化它只是一件繁琐的工作。

另一方面,有关 Windows 深层内部结构的文档几乎不存在,而且我不知道数据结构以某种方式暴露在外部。我不是 Windows 专家,但除非 Windows API 明确提供此类信息,否则它可能根本不可用。

Mark Russinovich 的 SysInternals 实用程序可能正在使用任何可用的东西;第一个想到的是 FileMon。查看这些可能会给您一些线索。更新:我刚刚得知 SysInternals Handles.exe更接近您想要的。

如果你能弄清楚这一点,那就太好了;否则,您可能有兴趣捕获发生的文件打开/关闭操作:Windows API 提供了大量所谓的 Hook: http: //msdn.microsoft.com/en-us/library/ms997537.aspx。挂钩允许您在系统中发生某些事情时请求通知。我相信有一个程序会告诉您系统范围内的程序何时打开文件。因此,您可以创建自己的在收听挂钩期间打开的文件列表。我不确定,但我怀疑这可能就是 FileMon 所做的。

Windows API,包括钩子函数,可以从 C 语言访问。系统范围的钩子将要求您创建一个 DLL 来与您的程序一起加载。

希望这些提示可以帮助您入门。