You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:43:22