c++如何判断文件当前是否被其他程序占用_尝试独占打开探测【避坑】

风晨君_7162

风晨君_7162

2026-03-24

306人浏览

原创

fopen独占打开失败不等于文件被占用,真正可靠的是系统API强制独占访问:Windows用CreateFile设dwShareMode=0并检查ERROR_SHARING_VIOLATION,Linux用open+flock/ fcntl加写锁。

c++如何判断文件当前是否被其他程序占用_尝试独占打开探测【避坑】

用 fopen 独占打开失败不等于文件被占用

Windows 下常见误解:调用 fopen("file.txt", "r+") 失败就断定“被其他程序锁了”。其实更可能是权限不足、路径不存在、或文件正被记事本这类以共享模式打开的程序占用——而它们根本没加独占锁。

真正可靠的探测方式,是绕过 C 运行时库,直接调用系统 API 强制尝试独占访问:

  • Windows 用 CreateFile,指定 dwShareMode = 0(禁止任何共享)和 dwCreationDisposition = OPEN_EXISTING
  • Linux/macOS 用 open 配合 O_EXCL | O_RDWR(注意:O_EXCL 单独对已存在文件无效,必须配合 O_CREAT 才生效;真想测占用,得用 flock 或 fcntl 加写锁)
  • fopen 和 std::fstream 默认走共享打开逻辑,完全无法感知其他进程的独占锁

Windows 下 CreateFile 返回 ERROR_SHARING_VIOLATION 才是关键信号

这是唯一能明确告诉你“有别的进程正以不兼容的共享模式打开该文件”的错误码。但要注意几个坑:

  • 必须传 GENERIC_READ | GENERIC_WRITE,哪怕你只读——否则某些程序(如 Excel)的只读打开也会导致失败,误判为“被占”
  • 如果文件本身只读(FILE_ATTRIBUTE_READONLY),CreateFile 会返回 ERROR_ACCESS_DENIED,不是 ERROR_SHARING_VIOLATION,别混为一谈
  • 调用后务必用 CloseHandle,否则你自己的句柄会持续占用,下次探测反而失败
  • 示例关键片段:
    HANDLE h = CreateFile(L"test.txt", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);<br>if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION) { /* 真被占 */ }

Linux 下别信 access() 或 stat(),它们完全不检测锁

这两个函数只查权限和元数据,对 flock、fcntl 锁完全无感。真实场景中:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 用 open("file", O_RDWR) 成功 ≠ 文件没被占——可能对方只加了读锁,你仍可打开
  • 真正要测“能否写入”,得紧接着 flock(fd, LOCK_EX | LOCK_NB) 或 fcntl(fd, F_SETLK, &fl) 尝试非阻塞加写锁
  • 如果 flock 返回 -1 且 errno == EWOULDBLOCK,说明已有写锁;若 errno == EAGAIN,含义相同(取决于内核版本)
  • 注意:flock 是建议性锁,对方不用它就完全无效;fcntl 更底层但也更复杂,且不同文件系统行为略有差异

跨平台封装时最容易忽略的点:缓存与时机

即使探测到“当前未被占用”,也不能保证下一毫秒仍空闲——文件锁是瞬态的。更麻烦的是:

  • Windows 上 NTFS 有延迟关闭机制:进程退出后,句柄可能几毫秒才真正释放,此时立刻重试 CreateFile 仍会失败
  • Linux 下 /proc/*/fd/ 可手动检查谁在用,但需要 root 权限,生产环境基本不可行
  • 不要在循环里高频重试(比如 while(1) sleep(1)),容易触发杀毒软件误报或系统资源警告
  • 真正健壮的做法是:探测 + 合理退避(如指数退避)+ 明确超时(比如最多等 5 秒),而不是执着于“立刻拿到”

文件占用本质是竞态条件,所有探测都是快照。想稳,就得接受“可能失败”这个前提,而不是把探测当成万能钥匙。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.25

354

5

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.26

3499

3

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.27

3038

6

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

2023.08.01

1548

3

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2759

5

windows无法访问共享电脑
windows无法访问共享电脑

在现代社会中,共享电脑是办公室和家庭的重要组成部分。然而,有时我们可能会遇到Windows无法访问共享电脑的问题。这个问题可能会导致数据无法共享,影响工作和生活的正常进行。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.08

3370

4

windows自动更新
windows自动更新

Windows操作系统的自动更新功能可以确保系统及时获取最新的补丁和安全更新,以提高系统的稳定性和安全性。然而,有时候我们可能希望暂时或永久地关闭Windows的自动更新功能。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

1737

3

windows boot manager
windows boot manager

windows boot manager无法开机的解决方法:1、系统文件损坏,使用Windows安装光盘或USB启动盘进入恢复环境,选择修复计算机,然后选择自动修复;2、引导顺序错误,进入恢复环境,选择命令提示符,输入命令"bootrec /fixboot"和"bootrec /fixmbr",然后重新启动计算机;3、硬件问题,使用硬盘检测工具进行扫描和修复;4、重装操作系统。本专题还提供其他解决

2023.08.28

2537

4

windows锁屏快捷键
windows锁屏快捷键

windows锁屏快捷键是Windows键+L、Ctrl+Alt+Del、Windows键+D、Windows键+P和Windows键+R。本专题为大家提供windows相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.30

5527

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习