使用inotify检测USB插入后opendir遇权限拒绝问题排查
问题原因
核心是USB挂载的时序与inotify事件触发时机不匹配:
Linux系统挂载USB设备的流程是分步执行的:
- 先创建
/media/michel/MYUSB挂载点目录 - 将USB设备的文件系统挂载到该目录
- 调整挂载点的权限/归属,确保当前用户可访问
你通过IN_CREATE|IN_ISDIR监控到的事件,是在第一步完成后就触发的——此时USB文件系统还没挂载,你访问的只是系统临时创建的空目录,这个目录的权限通常是root所有,普通用户调用opendir自然会返回权限拒绝错误。
而提前插入USB时,整个挂载流程已经完成,目录的权限和归属都已调整为当前用户可访问,所以opendir能正常执行。
解决办法
1. 延迟重试访问
收到inotify事件后,不要立即调用opendir,而是短暂等待后重试(挂载操作通常在几百毫秒内完成),示例代码如下:
// 收到事件后的处理逻辑 DIR *usbdir = NULL; int retry_count = 5; const int retry_delay_ms = 200; while (retry_count-- > 0 && usbdir == NULL) { usbdir = opendir(folders); if (usbdir == NULL) { // 等待后重试,usleep单位为微秒 usleep(retry_delay_ms * 1000); } } if (usbdir == NULL) { perror("Failed to open USB directory after retries"); } else { // 执行目录扫描逻辑 // ... closedir(usbdir); }
2. 监控挂载完成的属性变化
除了IN_CREATE,额外监控IN_ATTRIB事件——当USB文件系统挂载完成后,挂载点的文件属性(如文件系统类型、权限)会发生变化,触发该事件。此时再调用opendir,就能确保访问的是挂载后的USB文件系统。
修改inotify_add_watch的事件参数:
evtfd = inotify_add_watch(notifyfd, folders, IN_CREATE|IN_ISDIR|IN_ATTRIB);
然后在事件处理时,优先响应IN_ATTRIB事件(或同时处理,确保挂载完成后再操作)。
3. 结合挂载状态验证
可以读取/proc/mounts文件,检查目标目录是否已经完成挂载,确认后再执行目录扫描。比如通过解析/proc/mounts的内容,查找是否有/media/michel/MYUSB对应的挂载条目。
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

