Linux下如何统计当前运行的线程数量?
不调用Shell,在C++中统计系统运行的线程总数
当然可以实现——你给出的ps -eo nlwp | tail -n +2 | awk '{ num_threads += $1 } END { print num_threads }'命令本质上也是通过读取/proc文件系统的内容来统计线程数的,我们完全可以直接在C++代码里解析/proc下的文件,不需要依赖Shell或外部进程。
实现原理
Linux系统中,每个进程在/proc目录下都有一个以PID(进程ID)命名的子目录,其中:
status文件包含Threads:字段,直接记录了该进程的线程数量;stat文件的第20个空格分隔字段(从1开始计数)也存储了线程数。
我们只需要遍历/proc下所有以数字命名的目录(即进程目录),读取每个进程的线程数并累加即可。
实现代码(C++17及以上,使用std::filesystem)
#include <iostream> #include <filesystem> #include <fstream> #include <string> #include <cctype> namespace fs = std::filesystem; // 判断目录名是否为纯数字(即PID) bool is_pid_dir(const std::string& dir_name) { for (char c : dir_name) { if (!std::isdigit(c)) { return false; } } return true; } int main() { unsigned long long total_threads = 0; const std::string proc_root = "/proc"; try { // 遍历/proc目录下的所有条目 for (const auto& entry : fs::directory_iterator(proc_root)) { if (entry.is_directory() && is_pid_dir(entry.path().filename().string())) { std::ifstream status_file(entry.path() / "status"); std::string line; // 读取status文件,找到Threads字段 while (std::getline(status_file, line)) { if (line.substr(0, 8) == "Threads:") { // 提取字段后的数字部分 size_t num_start = line.find_first_not_of(" \t", 8); if (num_start != std::string::npos) { total_threads += std::stoull(line.substr(num_start)); } break; // 找到目标字段后停止读取该文件 } } } } std::cout << "系统总线程数: " << total_threads << std::endl; } catch (const std::exception& e) { std::cerr << "执行错误: " << e.what() << std::endl; return 1; } return 0; }
编译命令(部分新版本GCC无需-lstdc++fs):
g++ -std=c++17 thread_counter.cpp -o thread_counter -lstdc++fs
兼容旧版本C++的实现(使用POSIX目录操作)
如果你的环境不支持C++17的std::filesystem,可以用传统的opendir/readdir接口实现:
#include <iostream> #include <fstream> #include <string> #include <cctype> #include <dirent.h> #include <cstring> // 判断目录名是否为纯数字 bool is_pid_dir(const char* dir_name) { for (int i = 0; dir_name[i] != '\0'; ++i) { if (!std::isdigit(dir_name[i])) { return false; } } return true; } int main() { unsigned long long total_threads = 0; const char* proc_root = "/proc"; // 打开/proc目录 DIR* proc_dir = opendir(proc_root); if (!proc_dir) { std::cerr << "无法打开/proc目录: 权限不足或系统不支持" << std::endl; return 1; } struct dirent* entry; while ((entry = readdir(proc_dir)) != nullptr) { // 只处理数字命名的目录 if (entry->d_type == DT_DIR && is_pid_dir(entry->d_name)) { std::string status_path = std::string(proc_root) + "/" + entry->d_name + "/status"; std::ifstream status_file(status_path); if (!status_file.is_open()) { continue; // 跳过无权限访问的进程目录 } std::string line; while (std::getline(status_file, line)) { if (line.compare(0, 8, "Threads:") == 0) { size_t num_start = line.find_first_not_of(" \t", 8); if (num_start != std::string::npos) { total_threads += std::stoull(line.substr(num_start)); } break; } } } } closedir(proc_dir); std::cout << "系统总线程数: " << total_threads << std::endl; return 0; }
编译命令:
g++ -std=c++11 thread_counter_old.cpp -o thread_counter_old
优势
这种直接操作/proc的方式,相比调用Shell命令:
- 避免了创建子进程、管道通信的开销,效率更高;
- 不需要依赖外部工具,代码可移植性更强(只要是Linux系统都支持
/proc); - 可以灵活扩展,比如同时统计特定用户的线程数、过滤特定进程等。
内容的提问来源于stack exchange,提问作者Roman Kukushkin
相关产品推荐
相关产品推荐

