如何在macOS上重实现lsof +D以避免两次调用stat(2)?
利用stat对象重实现lsof +D功能的关键信息
我用lsof +D /Users/jack/Downloads检测指定目录下被进程打开的文件,示例输出如下:
% lsof +D /Users/jack/Downloads Spotify 1431 jack 75r DIR 1,6 128 37333 /Users/jack/Downloads/file1.png Dock 1439 jack 13r DIR 1,6 128 37333 /Users/jack/Downloads/foo.psd zsh 6644 jack cwd DIR 1,6 128 37333 /Users/jack/Downloads/foo.bmp
根据lsof(8)手册,+D选项会遍历目标目录树,对每个文件/目录调用stat(2)构建文件列表,再和打开文件匹配,效率不高。而我在调用lsof前已经用Python遍历目录并调用os.stat,导致stat(2)被重复调用两次,所以想知道stat对象里有哪些信息可以用来自己实现这个功能。
stat对象中可用于实现该功能的核心信息
- 设备ID(st_dev):文件所在存储设备的唯一标识符,用来区分不同磁盘、分区等设备。
- inode号(st_ino):文件在所属文件系统中的唯一标识,这是匹配打开文件与目录文件的核心依据——只要两个文件的
st_dev和st_ino完全一致,就代表是同一个文件,不受路径变更影响。 - 文件类型(st_mode):通过位掩码可判断文件是普通文件、目录、符号链接等类型,对应lsof输出中的
DIR这类标识。 - 辅助校验信息:文件大小(st_size)、修改/访问/变更时间戳(st_mtime、st_atime、st_ctime),这些可作为额外匹配校验项,不过优先级低于
st_dev和st_ino。
基本实现思路
先用Python遍历目标目录,收集所有文件的st_dev、st_ino及对应路径;再读取系统中进程的打开文件信息(比如Linux下读/proc/<pid>/fd目录,macOS下利用/dev/fd相关机制),提取每个打开文件的st_dev和st_ino,与之前收集的目录文件信息做匹配,即可找出指定目录下被进程打开的文件。
内容的提问来源于stack exchange,提问作者HelloWorld
相关产品推荐
相关产品推荐

