一尘不染

解析/ proc /文件是否安全?

linux

我想解析/proc/net/tcp/,但是安全吗?

我应该如何打开文件/proc/并从中读取文件,不要害怕其他一些进程(或操作系统本身)会在同一时间对其进行更改?


阅读 267

收藏
2020-06-03

共1个答案

一尘不染

一般来说,没有。 (因此,这里的大多数答案都是错误的。)根据您想要的属性,它 可能
是安全的。但是,如果您过多地假设中的文件一致性,则很容易在代码中导致错误/proc。例如,请查看此错误,该错误来自假设它/proc/mounts是一致的快照

例如:

  • /proc/uptime 有人在另一个答案中提到过,这 完全原子的 -但 仅从 不到两年的 Linux 2.6.30开始 。因此,直到那时,即使这个很小的琐碎文件也一直处于竞争状态,并且仍然存在于大多数企业内核中。请参阅fs/proc/uptime.c以获取当前源或使其变为原子的提交。在2.6.30之前的内核上,您可以open将文件read进行一些修改,然后read再进行一次返回操作,则得到的文件将与第一部分不一致。(我只是演示了这一点-自己尝试一下很有趣。)

  • /proc/mounts 在单个read系统调用中原子的 因此,如果read一次全部读取整个文件,则将获得系统上安装点的单个一致快照。但是,如果您使用多个read系统调用-如果文件很大,那么如果您使用常规I / O库并且不特别注意此问题,就会发生这种情况-您将遇到麻烦健康)状况。不仅您将无法获得一致的快照,而且在您开始之前就存在并且从未停止存在的挂载点可能会丢失。要看到它的原子的一个read(),在看m_start()fs/namespace.c,看它抢信号灯,门卫挂载点的列表,其中它保持直到m_stop(),这就是所谓的时read()已经完成了。要查看可能出问题的地方,(与我上面链接的错误相同)/proc/mounts

  • /proc/net/tcp ,这实际上是您要问的那个,甚至没有那么一致。它 仅在表的每一行中都是原子的 。要查看此信息,请在同一文件listening_get_next()net/ipv4/tcp_ipv4.c及其established_get_next()下方查看,并依次查看它们在每个条目上取下的锁。我没有方便的repro代码来证明行与行之间缺乏一致性,但是那里(或任何其他地方)没有锁可以使它保持一致。如果您考虑一下,这是有道理的-网络通常是系统的一个非常繁忙的部分,因此在此诊断工具中提供一致的视图是不值得的开销。

/proc/net/tcp在每一行中保持原子状态的另一部分是缓冲seq_read(),您可以读fs/seq_file.c。这样可以确保一旦您read()将一行的一部分包含在内,整个行的文本将保留在缓冲区中,以便下一read()行在开始新行之前将获得该行的其余部分。/proc/mounts即使执行多次read()调用,也使用相同的机制使每一行保持原子状态,这也是/proc/uptime新内核中用于保持原子性的机制。这种机制也
没有 缓冲整个文件,因为内核是谨慎的内存使用。

其中的大多数文件/proc至少与一致/proc/net/tcp,每行在提供的任何信息中均具有一个条目的一致图片,因为它们大多数使用相同的seq_file抽象。/proc/uptime但是,如示例所示,某些文件直到seq_file2009年仍在迁移使用。我敢打赌,仍有一些使用较旧的机制,甚至没有这种原子性。这些警告很少记录。对于给定的文件,您唯一的保证是阅读源代码。

对于/proc/net/tcp,您可以阅读并解析每一行而不必担心。但是,如果您尝试一次从多行中得出任何结论,请注意,在阅读时,其他进程和内核
对其 进行 更改,并且很可能会产生错误。

2020-06-03