当我运行命令cat / proc / cpuinfo时会发生什么?


Answers:


72

每当您在下读取文件时/proc,这都会在内核中调用一些代码,该代码计算要读取的文本作为文件内容。内容是即时生成的,这说明了为什么几乎所有文件的时间都报告为现在,文件的大小报告为0的原因-在这里您应将0表示为“不知道”。与通常的文件系统不同,安装在上的文件系统/proc称为procfs,不会从磁盘或其他存储介质(例如FAT,ext2,zfs等)或网络(例如NFS,Samba等)加载数据。并且不调用用户代码(与FUSE不同)。

大多数非BSD Unix中都存在Procfs。它开始于AT&T的UNIX第8版的Bell Labs中,作为一种报告过程信息的方法(并且ps通常是通读信息的漂亮打印机/proc)。大多数procfs实现都有一个文件或目录,/proc/123用于报告有关PID 123进程的信息。Linux扩展了proc文件系统,其中包含更多条目,用于报告系统状态,包括您的示例/proc/cpuinfo

过去,Linux /proc收购了各种文件,这些文件提供了有关驱动程序的信息,但是现在不赞成使用,而是使用/sys/proc现在发展缓慢。条目像/proc/bus/proc/fs/ext4保持原样以保持向后兼容性,但是在之下创建了更新的类似接口/sys。在这个答案中,我将重点介绍Linux。

/proc关于Linux的文档的第一个和第二个入口点是:

  1. proc(5)手册页 ;
  2. /proc文件系统中的内核文档

当文档没有涵盖您的第三个入口点时,请阅读源代码。您可以在计算机上下载源代码,但这是一个庞大的程序,而Linux交叉引用LXR是一个很大的帮助。(LXR有很多变体;lxr.linux.no到目前为止,运行的是最好的一种,但是不幸的是,该站点经常停下来。)需要一点C的知识,但是您不必是一名程序员,就可以找到一个神秘的价值。 。

/proc条目的核心处理在fs/proc目录中。任何驱动程序都可以在中注册条目/proc(尽管如上所述,现在不建议使用/sys),因此,如果您找不到要查找的内容fs/proc,请在其他地方查找。驱动程序调用在中声明的函数include/linux/proc_fs.h高达3.9的内核版本提供了功能create_proc_entry和一些包装器(尤其是create_proc_read_entry),而3.10或更高版本的内核仅提供了proc_createproc_create_data(以及更多)。

/proc/cpuinfo作为一个例子,对于一个搜索"cpuinfo"导致你调用proc_create("cpuinfo, …")fs/proc/cpuinfo.c。您可以看到该代码几乎是样板代码:由于大多数文件/proc仅转储一些文本数据,因此可以使用辅助函数来实现。只有一个seq_operations结构,真正的实质是cpuinfo_op数据结构中的数据结构,它通常与结构相关,通常在arch/<architecture>/kernel/setup.c(或有时在一个不同的文件中)定义。以x86为例,我们得到了arch/x86/kernel/cpu/proc.c。那里的主要功能是show_cpuinfo,打印出所需的文件内容;基础架构的其余部分在那里以请求数据的速度将数据馈送到读取过程。您可以从内核中各种变量的数据中看到正在动态组装的数据,包括一些即时计算出的数字,例如CPU频率

的很大一部分/proc是中的每个进程的信息/proc/<PID>。这些条目fs/proc/base.ctgid_base_stuff数组中注册; 在此注册的某些功能在其他文件中定义。让我们看一下如何生成这些条目的一些示例:

的另一个重要方面/proc/proc/sys,它是的直接接口sysctl。从此层次结构中的条目读取将返回相应sysctl值的值,而写入将设置sysctl值。sysctl的入口点在中fs/proc/proc_sysctl.c。系统与register_sysctl和朋友有自己的注册系统。


59

当试图了解幕后发生的魔术时,你最好的朋友是strace。学习操作该工具是您可以做的最好的事情之一,以便更好地了解幕后发生的疯狂魔术。

$ strace -s 200 -m strace.log cat /proc/cpuinfo
...
read(3, "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 37\nmodel name\t: Intel(R) Core(TM) i5 CPU       M 560  @ 2.67GHz\nstepping\t: 5\nmicrocode\t: 0x4\ncpu MHz\t\t: 1199.000\ncache size\t: 3072 KB\nphy"..., 65536) = 3464
write(1, "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 37\nmodel name\t: Intel(R) Core(TM) i5 CPU       M 560  @ 2.67GHz\nstepping\t: 5\nmicrocode\t: 0x4\ncpu MHz\t\t: 1199.000\ncache size\t: 3072 KB\nphy"..., 3464) = 3464
read(3, "", 65536)                      = 0
close(3)                                = 0
...

从上面的输出中,您可以看到这/proc/cpuinfo只是一个普通文件,或者至少看起来像是一个文件。因此,让我们深入研究。

深潜

#1-与ls ..

从文件本身看,它似乎只是“一个文件”。

$ ls -l /proc/cpuinfo 
-r--r--r--. 1 root root 0 Mar 26 22:45 /proc/cpuinfo

但是请仔细看看。我们得到的第一个提示是它的特殊性,请注意文件的大小为0字节。

#2-统计

如果现在使用来查看文件,stat则可以得到下一个暗示,关于/proc/cpuinfo

运行#1
$ stat /proc/cpuinfo 
  File: ‘/proc/cpuinfo’
  Size: 0           Blocks: 0          IO Block: 1024   regular empty file
Device: 3h/3dInode: 4026532023  Links: 1
Access: (0444/-r--r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:proc_t:s0
Access: 2014-03-26 22:46:18.390753719 -0400
Modify: 2014-03-26 22:46:18.390753719 -0400
Change: 2014-03-26 22:46:18.390753719 -0400
 Birth: -
运行#2
$ stat /proc/cpuinfo 
  File: ‘/proc/cpuinfo’
  Size: 0           Blocks: 0          IO Block: 1024   regular empty file
Device: 3h/3dInode: 4026532023  Links: 1
Access: (0444/-r--r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:proc_t:s0
Access: 2014-03-26 22:46:19.945753704 -0400
Modify: 2014-03-26 22:46:19.945753704 -0400
Change: 2014-03-26 22:46:19.945753704 -0400
 Birth: -

注意到访问,修改和更改时间了吗?他们会为每次访问不断更改。这三者都会像这样改变是非常不寻常的。除非进行编辑,否则文件的时间戳属性通常保持不变。

#3-带文件

另一个线索表明此文件不是常规文件:

$ file /proc/cpuinfo 
/proc/cpuinfo: empty

如果它是命名管道的某种表现形式,它将显示类似于以下文件之一:

$ ls -l /dev/initctl /dev/zero 
prw-------. 1 root root    0 Mar 26 20:09 /dev/initctl
crw-rw-rw-. 1 root root 1, 5 Mar 27 00:39 /dev/zero

$ file /dev/initctl /dev/zero 
/dev/initctl: fifo (named pipe)
/dev/zero:    character special

如果我们触摸emptyfile/proc/cpuinfo看起来确实更像文件,然后是管道:

$ touch emptyfile
$ ls -l emptyfile 
-rw-rw-r--. 1 saml saml 0 Mar 27 07:40 emptyfile
$ file emptyfile 
emptyfile: empty
#4-带支架

因此,在这一点上,我们需要退后一步并缩小一点。我们正在查看一个特定的文件,但也许我们应该在查看该文件所在的文件系统。为此,我们可以使用mount命令。

$ mount | grep " /proc "
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)

确定,因此文件系统类型为proc。所以/proc是不同的文件系统类型,这就是我们的暗示下的文件/proc是特殊的。它们不仅是您运行的铣削文件。因此,让我们找到有关使proc文件系统与众不同的更多信息。

看一下mount的手册页:

proc文件系统不与特殊设备关联,并且在挂载该文件系统时,可以使用诸如proc之类的任意关键字代替设备规范。(通常的选择都不是那么幸运:umount的错误消息“ none busy”可能会令人困惑。)

如果我们看一下proc的手册页:

proc文件系统是伪文件系统,用作内核数据结构的接口。它通常安装在/ proc上。它大多数是只读的,但是有些文件允许更改内核变量。

在相同的手册页中往下一点:

/ proc / cpuinfo

这是CPU和系统体系结构相关项的集合,对于每种受支持的体系结构,都有不同的列表。两个常见的条目是处理器,它给出CPU编号和bogomips。在内核初始化期间计算的系统常数。SMP机器具有每个CPU的信息。lscpu(1)命令从该文件收集其信息。

手册页底部是对内核文档的引用,您可以在此处找到标题为:/ proc FILESYSTEM的内核文档。引用该文档:

proc文件系统充当内核中内部数据结构的接口。它可用于获取有关系统的信息并在运行时(sysctl)更改某些内核参数。

结论

那么我们在这里学到了什么?好吧,既然这/proc被称为伪文件系统,而且是“内部数据结构的接口”,则可以安全地假设其中的项目不是实际文件,而只是看起来像文件的表现形式,但实际上不是。

我将以该报价结束,该报价显然曾经是man 5 proc2004年左右版本的早期版本, 但由于任何原因不再包含在内。注意:我不确定为什么将其删除,因为它很好地描述了什么/proc

GNU / Linux系统上的/ proc目录提供了类似于文件系统的内核接口。这允许应用程序和用户使用正常的文件系统I / O操作从内核中获取信息并在内核中设置值。

proc文件系统有时被称为过程信息伪文件系统。它不包含“实际”文件,而是包含运行时系统信息(例如,系统内存,安装的设备,硬件配置等)。因此,它可以被视为内核的控制和信息中心。实际上,很多系统实用程序只是对该目录中文件的调用。例如,列出内核加载的模块的命令lsmod与'cat / proc / modules'基本上相同,而列出连接到系统PCI总线的设备的lspci与'cat / proc / pci'。通过更改此目录中的文件,可以在系统运行时更改内核参数。

来源: proc伪文件系统

参考文献


1
很酷,:)这是我看到问题后首先尝试的事情:strace -o catcpuproc.txt cat /proc/cpuinfo
mkc 2014年

1
好答案!在Linux上,如果您想更深入地研究,则proc文件系统的源位于内核源文件中的fs / proc中。您会看到有一个fs / proc / cpuinfo.c,但是不幸的是,它很空,因为繁重的工作分散在arch /上,因为它依赖于体系结构。有关更简单的示例,请参见fs / proc / uptime.c。通过浏览该文件,我们可以猜测uptime_proc_show是使我们获得所需数据的主力军,我们可以通过深入研究其调用的函数来对其进行进一步的研究。要了解seq_file接口及其在procfs中的使用方式,请参阅:
Steven D


1
@slm:+1,很好的答案。但是对我来说,第一个提示是它是一个特殊的文件,它的大小为^^ 0字节,但是您可以从中得到很多东西(有点像某些管道文件)。
Olivier Dulac 2014年

@OlivierDulac-好点。根据您的反馈,我进行了其他修改。LMK如果可以进一步改进。谢谢。
slm

14

@slm给出的答案非常全面,但是我认为更简单的解释可能来自于视角的改变。

在日常使用中,我们可以将文件视为实体。存储在某些设备上的大量数据。这使/ proc / cpuinfo这样的文件非常神秘和混乱。但是,如果我们将文件视为接口,那么这一切都是非常合理的。一种向某程序发送数据的方法。

以这种方式发送和接收数据的程序是文件系统或驱动程序(取决于定义这些术语的方式,定义可能太宽泛也太狭窄)。重要的一点是,其中一些程序使用硬件设备来存储和检索通过此接口发送的数据。但不是所有的。

使用存储设备(至少直接使用)的文件系统的一些示例是:

  • 使用查询或计算数据的文件系统。Proc是一个示例,因为它从各种内核模块获取数据。一个极端的例子是πfs(github.com/philipl/pifs)
  • 所有FUSE文件系统,使用常规用户空间程序处理数据
  • 可以即时转换另一个文件系统的数据的文件系统,例如使用加密,压缩甚至音频转码(khenriks.github.io/mp3fs/)

Plan9 OS(http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs)是将文件用作常规编程接口的一个极端示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.