用 getpid() 获取进程 id 最简单,但需注意头文件、平台差异及 pid namespace 隔离:linux/macos 直接调用,windows 推荐 getcurrentprocessid() 或 _getpid();统一用 pid_t 类型;std::this_thread::get_id() 是线程 id,不可混淆。

用 getpid() 获取进程 ID 最简单,但要注意头文件和平台差异
Linux/macOS 下直接调用 getpid() 就行,Windows 也支持(通过 POSIX 兼容层),但得确保链接了 -lmsvcrt 或使用 MSVC 默认链接;头文件统一用 <unistd.h></unistd.h> —— 注意:MSVC 的 <unistd.h></unistd.h> 是非标准扩展,某些旧版本可能没有,此时得 fallback 到 _getpid()。
- Clang/GCC/Linux/macOS:包含
<unistd.h></unistd.h>,直接用getpid() - MSVC(2015+):启用 `/D _CRT_SECURE_NO_WARNINGS` 后,
<io.h></io.h>或<process.h></process.h>提供_getpid(),返回值类型和getpid()一致(pid_t) - CMake 项目里别漏掉
set(CMAKE_CXX_STANDARD 17),否则某些 stdlib 实现可能不暴露pid_t定义
std::this_thread::get_id() 不是进程 ID,别混淆
std::this_thread::get_id() 返回的是线程 ID,类型是 std::thread::id,和操作系统级的进程 ID 完全无关。有人在日志里误用它替代 getpid(),结果发现多进程场景下所有子进程日志都显示“相同 ID”——其实是线程 ID 在不同进程里碰巧相等,纯属巧合。
- 进程 ID 是全局唯一整数(如 1234),线程 ID 是实现定义的对象,不可跨进程比较
- 若需同时记录进程和线程 ID,必须分开调用:
getpid()+std::this_thread::get_id() - Windows 上用
GetCurrentProcessId()更可靠,但它是 Win32 API,需包含<windows.h></windows.h>,且无法和 POSIX 代码共存于同一头文件中
跨平台封装时,避免宏地狱,优先用编译期判断
用 #ifdef _WIN32 套一层函数封装没问题,但别层层嵌套宏来选头文件或函数名。更稳的方式是写一个 inline 函数,在编译期就确定调用路径,让链接器不看到未使用的符号。
inline pid_t get_current_pid() {
#ifdef _WIN32
return static_cast<pid_t>(GetCurrentProcessId());
#else
return getpid();
#endif
}
- 别用
#define getpid GetCurrentProcessId这类粗暴替换,会破坏 IDE 跳转和静态分析 - 返回类型统一用
pid_t,不要用int或long,否则在某些嵌入式平台(如 ARM64 Linux)上可能截断 - 如果项目禁用 Win32 API,只能走
_getpid(),记得检查其返回值是否为 -1 并 errno 是否为ENOSYS(极少见,但 Cygwin/MinGW 某些配置下可能发生)
调试时发现 getpid() 总返回 1?可能是容器或 PID namespace 隔离
在 Docker 容器、systemd --scope 或 unshare 创建的 PID namespace 里,getpid() 返回的是 namespace 内部的 PID(通常是 1),不是宿主机 PID。这不是 bug,是内核机制使然。
立即学习“C++免费学习笔记(深入)”;
- 想获取宿主机 PID,得读
/proc/1/ns/pid或解析/proc/self/status中的NSpid:字段(Linux 4.1+) - macOS 和 Windows 没有等效 namespace 隔离,所以不会出现这个现象
- 日志中只打
getpid()结果却不说明运行环境,容易误导排查方向——尤其当服务在 Kubernetes 里重启后日志 ID 突然变小










