【问题标题】:Correct way of reading /proc/pid/status正确的阅读方式 /proc/pid/status
【发布时间】:2016-12-17 20:43:21
【问题描述】:

我是这样读/proc/<pid>/status的:

std::ifstream file(filename);
std::string line;
int numberOfLinesToRead = 4;
int linesRead = 0;

while (std::getline(file, line)) {
    // do stuff
    if (numberOfLinesToRead == ++linesRead) {
        break;
    }
}

我注意到在极少数情况下std::getline 挂起。

  1. 为什么会这样?我的印象是 proc 文件系统应该处于某种一致的状态,并且不应该出现缺少换行符的情况。我的假设是 getline 在发生 EOF/错误时返回 false
  2. 推荐的安全阅读方式是什么/proc/<pid>/status

【问题讨论】:

  • 这是逐行准备任何文本文件的“正确”方式。但是,如果您正在检查的进程在您读取文件时退出,那么与读取其他文本文件相比,行为可能会有所不同。并且没有std::getline 不返回布尔值,它返回流which can be used in a boolean expression
  • 关于第二个问题,从/proc/<some pid other than your own>/ 读取任何文件确实没有安全的方法,因为其他进程可能随时退出。您可能需要使用其他一些特定于 Linux 的系统调用来获取进程的状态,最好是在内核写入结构的直接系统调用中,而不是使用标准 C++ 库从文件中读取。
  • 我很惊讶这应该挂起。我怀疑这可能是编译器中的一个错误,也可能是OS 中的一个错误,因为如果另一个进程从您下面删除了一个文件,那么这应该会在您的文件描述符中干净地生成一个错误。而/proc 的行为应该与任何其他文件一样。你确定那个exact代码会导致他的错误吗?
  • @Galik 是的,非常确定。由gdb附加,检查回溯,继续执行,再次检查回溯。这里是:gist.github.com/lstipakov/95e6091d53e8f779c14800e6309109c0
  • @lstipakov,当你的程序挂起时,strace 的输出是什么?

标签: c++ linux string std procfs


【解决方案1】:

/proc is a virtual filesystem。这意味着从其中的“文件”读取与从普通文件系统读取不同。

如果进程退出,则从 /proc 中删除有关它的信息比如果它是真正的文件系统要快得多(这里涉及到脏缓存刷新延迟)。

记住这一点,想象在您读取尚未缓冲的下一行之前该进程退出。

解决方案是考虑文件丢失,因为您可能不需要有关不再存在的进程的信息,或者缓冲整个文件然后只解析它。

编辑:挂起过程显然与这是虚拟文件系统这一事实有关。它的行为方式与真实文件系统不同。由于这是特定的 fs 类型,因此问题可能出在 fs 驱动程序中。您提供的代码对于普通文件读取来说看起来不错。

【讨论】:

  • Alex,在问题的示例中,从 proc 读取文件的系统调用是什么?那里有几个系统调用吗?对整个文件(全有或全无)进行一次足够大的读取会更安全,然后从用户缓冲区中解析。
【解决方案2】:

也许更确定的方法是使用 fread 进入一个大缓冲区。状态文件很小,所以分配一个本地缓冲区并读取整个文件。

Example看第二个答案最简单的解决办法

这可能仍然会在 fopen 或 fread 上失败,但应该返回一个合理的错误。

【讨论】:

    猜你喜欢
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    • 2018-02-13
    • 2014-08-24
    相关资源
    最近更新 更多