使用 C++ 解析 /proc/stat

parsing /proc/stat using c++

本文关键字:proc stat 解析 C++ 使用      更新时间:2023-10-16

我是c++的新手,对Linux有点陌生。我有一个简单的项目,需要从/proc/stat 文件中解析 CPU 统计信息并计算 CPU 使用率。我尝试在完整的 bash 脚本上执行此操作。但我需要的是C ++。我只需要一点帮助。/proc/stat 给出了很多数字,我知道不同的列代表某些东西。如用户,尼斯,系统,空闲等。例如,我只想获取 Idle 值,并使用 c++ 将其存储为整数,我该怎么做?请帮忙。我现在尝试的只是使用 ifstream 和 getline() 获取我需要的整行

std::ifstream filestat("/proc/stat");
std::string line;
std::getline(filestat,line);

我得到的是这个。

cpu  349585 0 30513 875546 0 935 0 0 0 0

为了澄清我的问题,例如,我想获取875546值并使用 c++ 将其存储为整数。 我该怎么做? 谢谢

stat的格式在 proc(5) 手册页中有详细的描述。 您可以通过从 Linux 终端或在线运行命令man 5 proc来查看它。

上面描述的解析stat文件的方法适用于学术目的,但生产级解析器在使用这些方法时应采取额外的预防措施。

如果您需要一个生产级解析器C++用于/proc中的文件,您可以查看 pfs - 用于解析 procfs 的库(免责声明:我是图书馆的作者)

最大的问题通常是comm字段(文件中的第二个字段)。 根据手册页,此字段是一个字符串,应使用某种scanf风格和格式化程序%s"扫描"。但这是错误的!

comm字段由应用程序控制(可以使用prctl(PR_SET_NAME, ...)设置),并且可以轻松包含空格或括号,很容易导致99%的解析器失败。 像这样的简单更改不仅会返回一个错误的comm值,还会搞砸它后面的所有值。

解析文件的正确方法是以下方法之一:

  1. 选项#1:

    1. 读取文件的全部内容
    2. 查找第一个出现的"(">
    3. 查找最后一次出现的")">
    4. 分配这些索引之间的字符串
    5. 在最后一次出现")"之后解析文件的其余部分
  2. 选项#2:

    1. 读取 PID(文件中的第一个值)
    2. 读取 18 个字节(16 是最大的通信值 + 2 表示包装括号)
    3. 从该缓冲区中提取通信值,就像我们对选项 #1 所做的那样
    4. 找出值的实际长度,修复您的流并从那里继续阅读

你真的需要研究文件输入是如何工作的。这应该很简单。您只需要忽略3个字符"cpu",然后通读4整数值:

unsigned n;
if(std::ifstream("/proc/stat").ignore(3) >> n >> n >> n >> n)
{
// use n here...
std::cout << n << 'n';
}

或者,如果您已经有该行(也许您一次读取一行文件),则可以使用std::istringstream将该行转换为新的输入流:

std::ifstream filestat("/proc/stat");
std::string line;
std::getline(filestat, line);
unsigned n;
if(std::istringstream(line).ignore(3) >> n >> n >> n >> n)
{
// use n here...
std::cout << n << 'n';
}

有几种方法可以解决这个问题。您可以使用正则表达式库来获取字符串的一部分,或者如果您知道这总是转到第 5 个元素,那么您可以使用它:

std::string text = "cpu  349585 0 30513 875546 0 935 0 0 0 0";
std::istringstream iss(text);
std::vector<std::string> results(std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>());
int data = std::stoi( results[4] ); //check size before accessing 
std::cout << data << std::endl;

我希望它有所帮助。