Linux下用/proc/self/fd目录遍历fd列表最直接,需opendir/readdir过滤数字项并atoi转整数,用readlink获取路径、fstat和fcntl判断类型与状态,注意处理socket/eventfd等非常规fd及失效链接。

Linux下用/proc/self/fd目录遍历fd列表最直接
Linux内核通过/proc/self/fd为每个进程暴露其打开的文件描述符,这是最轻量、无需额外权限的方式。它本质是符号链接目录,每个数字子项指向实际打开的文件路径或设备。
- 遍历时需注意
readdir()返回的d_name是字符串,要atoi()转成整数fd才能用于后续fstat()或fcntl() - 某些fd(如标准输入/输出/错误)可能指向
pipe:[xxxx]、socket:[xxxx]或anon_inode:[eventfd],不能open()重打开,但可fstat()查类型和状态 - 必须检查
readlink()返回值:失败时errno == ENOENT表示fd已关闭但尚未被回收(极短暂窗口),应跳过 - 不要假设所有fd都对应常规文件——网络套接字、eventfd、timerfd、signalfd等都会出现在这里,
stat.st_mode无法区分,得靠readlink()目标字符串特征判断
用fstat()和fcntl()获取fd具体状态信息
fstat()能拿到基础元数据(大小、inode、设备号),但对套接字或管道几乎无用;真正关键的是fcntl(fd, F_GETFL)查打开标志(O_RDONLY/O_RDWR等),以及fcntl(fd, F_GETFD)看是否设置了FD_CLOEXEC。
-
fstat()对已关闭的fd会返回EBADF,务必先用fcntl(fd, F_GETFD)探测有效性——成功即有效fd -
fcntl(fd, F_GETFL)返回值需与O_ACCMODE掩码做&运算才能提取读写模式,直接比较O_RDONLY会错(因含其他标志位) - 对socket fd,
getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)可确认是SOCK_STREAM还是SOCK_DGRAM,但需确保fd确实是socket(否则ENOTSOCK) - 别依赖
/proc/self/fdinfo/<fd></fd>——它提供更细粒度信息(如socket状态、偏移量),但该文件在较老内核(open(),开销大
Windows上必须用NtQuerySystemInformation+ObjectBasicInformation
Windows没有等价于/proc的用户态接口,必须调用未公开的NTAPI:NtQuerySystemInformation(SystemHandleInformation, ...)获取当前进程所有句柄,再对每个句柄调用NtQueryObject()查类型和名称。
将提醒同步至 Windows/Outlook 日历。用户提及「提醒我」「设置提醒」「加到日历」「同步到日历」「日程」「calendar」「日历」时触发。支持Microsoft Graph API 设备代码流认证,无需 Web 服务器,直接写入用户 Outlook 日历。
- 需加载
ntdll.dll并手动解析SYSTEM_HANDLE_INFORMATION结构——它没有公开头文件定义,长度动态,必须循环读取直到Status == STATUS_INFO_LENGTH_MISMATCH - 句柄类型靠
ObjectTypeNumber查ObGetObjectType()对应名(如File、Thread、Event),但该编号随系统版本变化,硬编码会崩 - 获取句柄名称(如文件路径)需用
ObjectNameInformation类,但多数句柄(如TCP连接、注册表键)返回空名或\BaseNamedObjects\...,实际路径不可见 - 必须以管理员权限运行才能看到其他进程句柄,但查自身进程句柄不需要——不过仍需启用
SE_DEBUG_PRIVILEGE特权,否则NtQuerySystemInformation失败
跨平台封装要注意抽象层级和误差容忍
试图写“一套代码跑两边”容易踩坑:Linux的fd是纯数字索引,Windows句柄是内核对象指针值;Linux能精确看到文件路径,Windows大多只能知道类型。强行统一接口会让逻辑臃肿且丢失关键信息。
立即学习“C++免费学习笔记(深入)”;
- 不要设计
get_all_handles()返回统一结构体——Linux侧填fd和path,Windows侧填handle和type_name,字段语义根本不同 - 若只需判断“某fd是否打开”,Linux用
fcntl(fd, F_GETFD)足够;Windows则必须走完整NtQuery流程,无法简化 - 调试时发现fd数量异常?Linux下
/proc/self/status里的FDSize和FDMax只是分配上限,实际数量得数/proc/self/fd目录项;Windows里GetProcessHandleCount()返回的是近似值,不保证实时准确 - 生产环境慎用——频繁扫描fd列表在高并发服务中可能引发
/proc锁争用(Linux)或大量NTAPI调用(Windows),建议只在诊断工具中使用,非实时监控场景

















