linux 判断文件被其他进程占用
客户需要将转码器中电视直播频道的hls切片转存出来,在拷贝文件时,需要判断该切片文件是否正在被写入,否则拷贝出来的切片文件不完整。
linux下程序fuser有这个功能,源码在psmisc包里,地址:https://gitlab.com/psmisc/psmisc,
fuser功能很强大,可以查找文件,目录,网络端口等,我们只用到文件部分
原理是遍历/proc下的进程目录,和fd中的描述符做比较
关键函数如下:
1 static void 2 check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, 3 struct inode_list *ino_head, const uid_t uid, const char access, 4 dev_t netdev) 5 { 6 char *dirpath, *filepath; 7 DIR *dirp; 8 struct dirent *direntry; 9 struct inode_list *ino_tmp; 10 struct device_list *dev_tmp; 11 struct stat st, lst; 12 13 if ((dirpath = malloc(MAX_PATHNAME)) == NULL) 14 return; 15 if ((filepath = malloc(MAX_PATHNAME)) == NULL) 16 return; 17 18 snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname); 19 if ((dirp = opendir(dirpath)) == NULL) 20 return; 21 while ((direntry = readdir(dirp)) != NULL) { 22 if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9') 23 continue; 24 25 snprintf(filepath, MAX_PATHNAME, "/proc/%d/%s/%s", 26 pid, dirname, direntry->d_name); 27 if (stat(filepath, &st) != 0) { 28 fprintf(stderr, "Cannot stat file %s: %s\n", 29 filepath, strerror(errno)); 30 } 31 else 32 { 33 for (dev_tmp = dev_head; dev_tmp != NULL; 34 dev_tmp = dev_tmp->next) { 35 if (st.st_dev == dev_tmp->device) { 36 if (access == ACCESS_FILE 37 && (lstat(filepath, &lst) == 0) 38 && (lst.st_mode & S_IWUSR)) { 39 add_matched_proc(dev_tmp->name, 40 pid, uid, 41 ACCESS_FILEWR | 42 access); 43 } else { 44 add_matched_proc(dev_tmp->name, 45 pid, uid, 46 access); 47 } 48 } 49 } 50 for (ino_tmp = ino_head; ino_tmp != NULL; 51 ino_tmp = ino_tmp->next) { 52 if (st.st_dev == ino_tmp->device 53 && st.st_ino == ino_tmp->inode) { 54 if (access == ACCESS_FILE 55 && (lstat(filepath, &lst) == 0) 56 && (lst.st_mode & S_IWUSR)) { 57 add_matched_proc(ino_tmp->name, 58 pid, uid, 59 ACCESS_FILEWR | 60 access); 61 } else { 62 add_matched_proc(ino_tmp->name, 63 pid, uid, 64 access); 65 } 66 } 67 } 68 } 69 } /* while fd_dent */ 70 closedir(dirp); 71 }
运行结果:
ps:
同学们测试时如使用vi打开文件,但是fuser未显示文件被占用,原因如下: