为什么 wc 和 stat 对 /proc/[pid]/cmdline 产生不同的结果?

Sha*_*hop 6 linux stat wc

我试图了解原因wcstat报告不同的事情/proc/[pid]/cmdline

wc说我的 shellcmdline文件大小为 6 个字节:

$ wc --bytes /proc/$$/cmdline
6 /proc/10425/cmdline
Run Code Online (Sandbox Code Playgroud)

stat表示文件大小为 0 字节:

$ stat --format='%s' /proc/$$/cmdline
0
Run Code Online (Sandbox Code Playgroud)

file同意stat

$ file /proc/$$/cmdline
/proc/10425/cmdline: empty
Run Code Online (Sandbox Code Playgroud)

cat给出这个输出:

$ cat -vE /proc/$$/cmdline
-bash^@
Run Code Online (Sandbox Code Playgroud)

所有这些都在 Linux 上进行,而不是在任何其他 *nix 操作系统上进行。

stat和程序是否wc有不同的算法来计算文件中的字节数?

ilk*_*chu 11

下面的文件/proc不是常规文件,而是由内核动态创建的虚拟文件。对于大多数(全部?)来说,系统不会事先计算大小,但读取它的程序只会获取要获取的任何数据。

wc你所做的和stat例如所做的之间的区别ls在于,在这里wc打开文件,读取它并计算它得到的内容,同时stat使用ls系统stat()调用向系统询问文件的元数据,包括大小(而且还获得例如所有者和权限)。对于虚拟文件,这些不会给出相同的结果。

如果运行 eg ls -l /proc/$$/,您将看到许多大小为 0 的文件,尽管其中大多数文件都可以读取数据。

设备节点/dev/sda类似,尽管在它们的情况下ls甚至不显示大小,而是显示设备编号。

特别是file,您可以file -s要求它只读取数据而不关心它是否是特殊文件。

  • 许多带有“-c”的“wc”实现都采用“stat()”作为优化来报告*常规*文件中的字节数。自版本 8.24 以来,GNU `wc` 有特殊情况来处理 /proc 和 /sys 中的文件。请参阅 https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=2662702b9e8643f62c670bbf2fa94b1be1ccf9af (7认同)
  • 对于“/dev/sda”,与任何其他文件一样,“stat”报告“lstat()”返回的内容。在 Linux 上,`lstat()` 在设备的 st_size 中返回 0,但您会发现其他一些系统返回底层存储设备的大小。另请参阅[如何在 bash 脚本中获取文件的大小?](https://unix.stackexchange.com/a/321502) (3认同)
  • 从技术意义上来说,它们是“常规文件”,不是 fifo、套接字、设备、符号链接或其他任何文件。不过,正如您所说,它们不是普通文件:仅在“read”时从内核数据结构具体化,而“stat”则通过不这样做而仅显示它们的存在和权限来保持便宜。 (2认同)
  • @StéphaneChazelas *许多带有 -c 的 `wc` 实现都诉诸于 `stat`...* 哦,亲爱的。谢谢你的留言。在我看来,这是一个极其错误的“优化”;但我确实需要知道,有一些可怜的家伙冒着风险并实际实施了它。对我来说,如果我想知道“stat”将提供的(可能是错误的)信息,我会使用“stat(1)”。如果我怀疑 `stat` 的输出可能是错误或误导性的,我会使用 `wc`:将文件作为文件打开,并读取和计算每个字节,这就是 `wc` 的*用途*。谢什。 (2认同)