Answers:
每当您在下读取文件时/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的文档的第一个和第二个入口点是:
proc(5)
手册页 ;/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_create
和proc_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.c
在tgid_base_stuff
数组中注册; 在此注册的某些功能在其他文件中定义。让我们看一下如何生成这些条目的一些示例:
cmdline
proc_pid_cmdline
在同一文件中生成。它在过程中找到数据并打印出来。clear_refs
,与到目前为止我们看到的条目不同,它是可写但不可读的。因此,proc_clear_refs_operations
结构定义了一个clear_refs_write
功能,但没有读取功能。cwd
是一个由声明的符号链接(有点神奇),proc_cwd_link
它查找进程的当前目录并将其作为链接内容返回。fd
是一个子目录。目录本身的操作在proc_fd_operations
数据结构中定义(除了枚举条目的函数(枚举proc_readfd
进程的打开文件)外,它们都是样板),而条目的操作则位于proc_fd_inode_operations中。的另一个重要方面/proc
是/proc/sys
,它是的直接接口sysctl
。从此层次结构中的条目读取将返回相应sysctl值的值,而写入将设置sysctl值。sysctl的入口点在中fs/proc/proc_sysctl.c
。系统与register_sysctl
和朋友有自己的注册系统。
当试图了解幕后发生的魔术时,你最好的朋友是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
只是一个普通文件,或者至少看起来像是一个文件。因此,让我们深入研究。
从文件本身看,它似乎只是“一个文件”。
$ ls -l /proc/cpuinfo
-r--r--r--. 1 root root 0 Mar 26 22:45 /proc/cpuinfo
但是请仔细看看。我们得到的第一个提示是它的特殊性,请注意文件的大小为0字节。
#2-统计如果现在使用来查看文件,stat
则可以得到下一个暗示,关于/proc/cpuinfo
。
$ 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 proc
2004年左右版本的早期版本, 但由于任何原因不再包含在内。注意:我不确定为什么将其删除,因为它很好地描述了什么/proc
:
GNU / Linux系统上的/ proc目录提供了类似于文件系统的内核接口。这允许应用程序和用户使用正常的文件系统I / O操作从内核中获取信息并在内核中设置值。
proc文件系统有时被称为过程信息伪文件系统。它不包含“实际”文件,而是包含运行时系统信息(例如,系统内存,安装的设备,硬件配置等)。因此,它可以被视为内核的控制和信息中心。实际上,很多系统实用程序只是对该目录中文件的调用。例如,列出内核加载的模块的命令lsmod与'cat / proc / modules'基本上相同,而列出连接到系统PCI总线的设备的lspci与'cat / proc / pci'。通过更改此目录中的文件,可以在系统运行时更改内核参数。
来源: proc伪文件系统
strace -o catcpuproc.txt cat /proc/cpuinfo
@slm给出的答案非常全面,但是我认为更简单的解释可能来自于视角的改变。
在日常使用中,我们可以将文件视为实体。存储在某些设备上的大量数据。这使/ proc / cpuinfo这样的文件非常神秘和混乱。但是,如果我们将文件视为接口,那么这一切都是非常合理的。一种向某程序发送数据的方法。
以这种方式发送和接收数据的程序是文件系统或驱动程序(取决于定义这些术语的方式,定义可能太宽泛也太狭窄)。重要的一点是,其中一些程序使用硬件设备来存储和检索通过此接口发送的数据。但不是所有的。
不使用存储设备(至少直接使用)的文件系统的一些示例是:
Plan9 OS(http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs)是将文件用作常规编程接口的一个极端示例。