/ proc / *如何工作?


62

有许多文件/proc,如/proc/cpuinfo/proc/meminfo/proc/devices等等,其中,打开时,返回系统信息。

这些文件实际上似乎不存在,因为file在它们上运行只能表明它们为空。

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

这些文件如何工作?

Answers:


72

实际上,这非常简单,至少在不需要实现细节的情况下。

首先,在Linux上,所有文件系统(ext2,ext3,btrfs,reiserfs,tmpfs,zfs等)都在内核中实现。有些可以通过FUSE卸载工作到用户级代码,而有些则仅以内核模块的形式出现(由于许可限制,本机ZFS是后者的一个显着示例),但是无论哪种方式都保留了内核组件。这是重要的基础。

当一个程序需要从文件中读取,它会发出不同的系统库调用,最终结束了在内核中的形式open()read()close()序列(可能seek()抛出的良好措施)。内核采用提供的路径和文件名,并通过文件系统和设备I / O层将其转换为对某些底层存储的物理读取请求(在许多情况下,还包括写入请求-例如考虑进行时间更新)。

但是,不必将这些请求专门转换为物理,持久性存储。内核的约定是发出特定的系统调用集将提供有关文件的内容。在我们的物理领域中确切存在“文件”的位置是此位置的第二位。

/proc通常安装所谓的procfs。这是一种特殊的文件系统类型,但是由于它是文件系统,因此它与ext3安装在某处的文件系统没有什么不同。因此,该请求将传递到procfs文件系统驱动程序代码,该代码了解所有这些文件和目录,并从内核数据结构返回特定的信息

在这种情况下,“存储层”是内核数据结构,并procfs提供了一个干净,方便的接口来访问它们。请记住,将procfs挂接起来/proc只是惯例。您可以轻松地将其安装在其他位置。实际上,有时这样做是可以的,例如在chroot监狱中,当运行于此的进程出于某种原因需要访问/ proc时。

如果您将值写入某个文件,则其工作方式相同。在内核级别,即转化为一系列open()seek()write()close()电话再次获得通过文件系统驱动程序; 同样,在这种特殊情况下,还会显示procfs代码。

您看到file返回的特定原因empty是,procfs公开的许多文件公开的大小为0字节。0字节大小可能是内核方面的一种优化(/ proc中的许多文件都是动态的,并且长度很容易变化,甚至从一个读取到下一个都可能变化,并且计算每个目录读取时每个文件的长度会可能非常昂贵)。对该注释进行评论,您可以通过运行strace或类似工具在您自己的系统上进行验证,然后file首先发出一个stat()调用以检测任何特殊文件,然后趁此机会报告文件大小是否为0 ,中止并将文件报告为空。

该行为实际上已记录在案,并且可以通过指定-s--special-filesfile调用中予以覆盖尽管如手册页中所述可能会有副作用。下面的引用来自2011年10月17日的BSD文件5.11手册页。

通常,文件仅尝试读取并确定stat(2)报告为普通文件的参数文件的类型。这可以防止出现问题,因为读取特殊文件可能会产生特殊的后果。指定该-s选项会使文件还读取作为块或字符特殊文件的参数文件。这对于确定原始磁盘分区(即块特殊文件)中数据的文件系统类型很有用。 此选项还导致文件忽略stat(2)报告的文件大小,因为在某些系统上它报告原始磁盘分区的大小为零。


5
当您用strace file /proc/version或观看时ltrace -S /proc/version,优化效果很小。它先执行一个stat()调用,然后发现大小为0,从而跳过open()-,但是在此之前它会加载多个魔术文件。
ott--

2
@ ott--这确实是一个奇怪的事件序列,但可能与您可以将多个文件名传递给的事实有关file。这样,文件会预先加载魔术文件,然后逐个参数处理命令行参数;而不是将加载的魔术文件移动到代码的“尝试确定特定文件属于哪种文件之前”部分,这会增加复杂性。调用stat()并根据其返回值采取行动基本上是无害的;增加跟踪其他内部状态风险的复杂性,从而导致引入错误。
CVn

@ ott--实际上,file报告“文件为空” 的原因是因为它调用stat来检测特殊文件(命名管道,设备等),并借此机会停止处理空文件。file -s /proc/version报告“ ASCII文本”。
吉尔斯2013年

4
@Gilles -s应该用于块/字符特殊设备。最终,我查看了file源代码,并在fsmagic.c的末尾看到了为什么它返回ASCII text而不是返回的解释emptyIf stat() tells us the file has zero length, report here that the file is empty, so we can skip all the work of opening and reading the file. But if the -s option has been given, we skip this optimization, since on some systems, stat() reports zero size for raw disk partitions.
ott--

15

在此目录中,您可以控制内核如何查看设备,调整内核设置,将设备添加到内核并再次删除它们。在此目录中,您可以直接查看内存使用情况和I / O统计信息。

您可以查看安装了哪些磁盘以及使用了哪些文件系统。简而言之,如果您知道要查找的内容,则可以从此目录检查Linux系统的每个方面。

/proc目录不是普通目录。如果要从引导CD引导并查看硬盘驱动器上的该目录,则将其视为空目录。当您在正常运行的系统下查看时,它可能会很大。但是,它似乎没有使用任何硬盘空间。这是因为它是一个虚拟文件系统。

由于/proc文件系统是一个虚拟文件系统并驻留在内存中,/proc因此每次Linux计算机重新引导时都会创建一个新的文件系统。

换句话说,它只是通过文件和目录类型接口轻松窥视Linux系统的勇气的一种手段。当您查看/proc目录中的文件时,您将直接查看Linux内核中的内存范围,并查看其内容。

文件系统中的图层

在此处输入图片说明

例子:

  • 在内部/proc,每个正在运行的进程都有一个目录,以其进程ID命名。这些目录包含具有有关进程的有用信息的文件,例如:
    • exe:这是指向从其开始处理的磁盘上文件的符号链接。
    • cwd:是到流程工作目录的符号链接。
    • wchan:当读取时,它返回进程正在等待的通道。
    • maps:读取时返回进程的内存映射。
  • /proc/uptime 以秒为单位的两个十进制值(以空格分隔)返回正常运行时间:
    • 自内核启动以来的时间。
    • 内核空闲的时间。
  • /proc/interrupts:有关中断的信息。
  • /proc/modules:有关模块列表。

有关更多详细信息,请参见man prockernel.org


“如果要从启动CD引导并查看硬盘驱动器上的该目录,您会发现它为空。” 这不是特定于/ proc的,它通常适用于尚未安装基础文件系统的任何安装点。如果从同一张启动CD进行启动,并执行类似的操作mount -t procfs procfs /mnt/proc,则将看到当前正在运行的内核的/ proc。
CVn

5

您是正确的,它们不是真实文件。

用最简单的术语来说,这是一种使用常规读写文件的方法与内核进行通讯的方法,而不是直接调用内核。这符合Unix的“一切都是文件”的哲学。

其中的文件/proc实际上并不存在,但是内核会对您在其中读取和写入的文件做出反应,而不是写入存储,而是报告信息或执行某些操作。

同样,其中的文件/dev也不是传统意义上的文件(尽管在某些系统上,其中的文件/dev可能实际存在于磁盘上,但它们所指的设备对它们没有太多影响)-它们使您可以交谈到使用普通Unix文件I / O API的设备-或使用它的任何设备(如外壳)


1
* nix更像是只能保护文件的文件。由于访问控制列表保留在文件系统中,因此可以使用文件系统驱动程序已经提供的通用机制来方便地保护特权资源。通过简化为从proc文件系统虚拟文件中读取,可以简化访问内核结构的工具的实现,并允许它们在没有提升权限的情况下运行。
Pekka

3

/proc目录内部有两种类型的内容,第一种是编号目录,第二种是系统信息文件。

/proc是一个虚拟文件系统。例如,如果您这样做了ls -l /proc/stat,您会注意到它的大小为0个字节,但是如果您执行“ cat / proc / stat”,则您将在文件中看到一些内容。

进行ls -l /proc,您会看到很多目录只有数字。这些数字代表进程ID(PID)。该编号目录内的文件与具有该特定PID的进程相对应。

在之下可用的某些文件/proc包含系统信息,例如cpuinfo,meminfo和loadavg。

一些Linux命令从这些/proc文件中读取信息并显示它。例如,free命令从/proc/meminfo文件中读取内存信息,对其进行格式化并显示。

要了解有关单个/proc文件的更多信息,请执行“ man 5 FILENAME”。

/proc/cmdline – Kernel command line
/proc/cpuinfo – Information about the processors.
/proc/devices – List of device drivers configured into the currently running kernel.
/proc/dma – Shows which DMA channels are being used at the moment.
/proc/fb – Frame Buffer devices.
/proc/filesystems – File systems supported by the kernel.
/proc/interrupts – Number of interrupts per IRQ on architecture.
/proc/iomem – This file shows the current map of the system’s memory for its various devices
/proc/ioports – provides a list of currently registered port regions used for input or output communication with a device
/proc/loadavg – Contains load average of the system
The first three columns measure CPU utilization of the last 1, 5, and 10 minute periods.
The fourth column shows the number of currently running processes and the total number of processes.
The last column displays the last process ID used.
/proc/locks – Displays the files currently locked by the kernel
Sample line:
1: POSIX ADVISORY WRITE 14375 08:03:114727 0 EOF
/proc/meminfo – Current utilization of primary memory on the system
/proc/misc – This file lists miscellaneous drivers registered on the miscellaneous major device, which is number 10
/proc/modules – Displays a list of all modules that have been loaded by the system
/proc/mounts – This file provides a quick list of all mounts in use by the system
/proc/partitions – Very detailed information on the various partitions currently available to the system
/proc/pci – Full listing of every PCI device on your system
/proc/stat – Keeps track of a variety of different statistics about the system since it was last restarted
/proc/swap – Measures swap space and its utilization
/proc/uptime – Contains information about uptime of the system
/proc/version – Version of the Linux kernel, gcc, name of the Linux flavor installed.

2
在我看来,这更像是“如何使用/ proc中的内容?”。而不是“ / proc如何工作?”。有用的信息,但不一定回答这个特定问题
CVn

/ proc中的每个文件都是运行时信息,这意味着当您在/ proc / meminfo中添加内容时,内核的一部分将运行一个函数,该函数生成文件内容。
Shailesh

3

最小的可运行示例

我认为理解这些东西的最好方法是实际使用它们,因此下面是一个创建procfs条目的内核模块:

myprocfs.c

#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_open, single_release */
#include <uapi/linux/stat.h> /* S_IRUSR */

static const char *filename = "lkmc_procfs";

static int show(struct seq_file *m, void *v)
{
    seq_printf(m, "abcd\n");
    return 0;
}

static int open(struct inode *inode, struct  file *file)
{
    return single_open(file, show, NULL);
}

static const struct file_operations fops = {
    .llseek = seq_lseek,
    .open = open,
    .owner = THIS_MODULE,
    .read = seq_read,
    .release = single_release,
};

static int myinit(void)
{
    proc_create(filename, 0, NULL, &fops);
    return 0;
}

static void myexit(void)
{
    remove_proc_entry(filename, NULL);
}

module_init(myinit)
module_exit(myexit)
MODULE_LICENSE("GPL");

然后我们以如下方式与它进行交互:

insmod procfs.ko
cat /proc/lkmc_procfs

并产生输出:

abcd

从这个例子中,我们清楚地看到,proc文件使我们能够实现任意“文件相关的系统调用”,如openreadllseek

这些系统调用然后可以用于与内核的任意通信。

因此,这些文件与文件系统中的实际文件没有任何关系,几乎所有文件都是如此。

例如,在我们的小示例中,我们只是简单地创建了一个无用的文件,该文件read始终返回abcd\n

这是我的全自动QEMU + Buildroot设置,可轻松安全地构建和使用此内核模块:

其他一些类似的接口包括:

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.