Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

What happens when I write cat /proc/cpuinfo. Is that a named pipe (or something else) to the OS which reads the CPU info on the fly and generate that text each time I call it?

share|improve this question
3  
I want to know :) –  Ramesh Mar 27 at 3:16

3 Answers 3

up vote 48 down vote accepted

Whenever you read a file under /proc, this invokes some code in the kernel which computes the text to read as the file content. The fact that the content is generated on the fly explains why almost all files have their time reported as now and their size reported as 0 — here you should read 0 as “don't know”. Unlike usual filesystems, the filesystem which is mounted on /proc, which is called procfs, doesn't load data from a disk or other storage media (like FAT, ext2, zfs, …) or over the network (like NFS, Samba, …) and doesn't call user code (unlike FUSE).

Procfs is present in most non-BSD unices. It started its life in AT&T's Bell Labs in UNIX 8th edition as a way to report information about processes (and ps is often a pretty-printer for information read through /proc). Most procfs implementations have a file or directory called /proc/123 to report information about the process with PID 123. Linux extends the proc filesystem with many more entries that report the state of the system, including your example /proc/cpuinfo.

In the past, Linux's /proc acquired various files that provide information about drivers, but this use is now deprecated in favor of /sys, and /proc now evolves slowly. Entries like /proc/bus and /proc/fs/ext4 remain where they are for backward compatibility, but newer similar interfaces are created under /sys. In this answer, I'll focus on Linux.

Your first and second entry points for documentation about /proc on Linux are:

  1. the proc(5) man page;
  2. The /proc filesystem in the kernel documentation.

Your third entry point, when the documentation doesn't cover it, is reading the source. You can download the source on your machine, but this is a huge program, and LXR, the Linux cross-reference, is a big help. (There are many variants of LXR; the one running on lxr.linux.no is the nicest by far but unfortunately the site is often down.) A little knowledge of C is required, but you don't need to be a programmer to track down a mysterious value.

The core handling of /proc entries is in the fs/proc directory. Any driver can register entries in /proc (though as indicated above this is now deprecated in favor of /sys), so if you don't find what you're looking for in fs/proc, look everywhere else. Drivers call functions declared in include/linux/proc_fs.h. Kernel versions up to 3.9 provide the functions create_proc_entry and some wrappers (especially create_proc_read_entry), and kernel versions 3.10 and above provide instead only proc_create and proc_create_data (and a few more).

Taking /proc/cpuinfo as an example, a search for "cpuinfo" leads you to the call to proc_create("cpuinfo, …") in fs/proc/cpuinfo.c. You can see that the code is pretty much boilerplate code: since most files under /proc just dump some text data, there are helper functions to do that. There is merely a seq_operations structure, and the real meat is in the cpuinfo_op data structure, which is architecture-dependent, usually defined in arch/<architecture>/kernel/setup.c (or sometimes a different file). Taking x86 as an example, we're led to arch/x86/kernel/cpu/proc.c. There the main function is show_cpuinfo, which prints out the desired file content; the rest of the infrastructure is there to feed the data to the reading process at the speed it requests it. You can see the data being assembled on the fly from data in various variables in the kernel, including a few numbers computed on the fly such as the CPU frequency.

A big part of /proc is the per-process information in /proc/<PID>. These entries are registered in fs/proc/base.c, in the tgid_base_stuff array; some functions registered here are defined in other files. Let's look at a few examples of how these entries are generated:

Another important area of /proc is /proc/sys, which is a direct interface to sysctl. Reading from an entry in this hierarchy returns the value of the corresponding sysctl value, and writing sets the sysctl value. The entry points for sysctl are in fs/proc/proc_sysctl.c. Sysctls have their own registration system with register_sysctl and friends.

share|improve this answer

When trying to gain insight into what sort of magic is happening behind the scenes your best friend is strace. Learning to operate this tool is one of the best things you can do to get a better appreciation for what crazy magic is happening behind the scenes.

$ 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
...

From the above output you can see that /proc/cpuinfo is just a regular file, or at least would appear to be one. So let's dig deeper.

Deeper dive

#1 - with ls..

Looking at the file itself it would appear to be "just a file".

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

But take a closer look. We get our first hint that its special, note the size of the file is 0 bytes.

#2 - with stat..

If we now look at the file using stat we can get our next hint that there is something special about /proc/cpuinfo.

run #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: -
run #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: -

Notice the Access, Modify, & Change times? They keep changing for each access. This is highly unusual that all 3 would change like that. Unless edited a file's timestamp attributes typically stay the same.

#3 - with file..

Yet another clue that this file is anything but a regular file:

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

If it were some manifestation of a named pipe it would show similar to one of these files:

$ 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

If we touch an emptyfile, /proc/cpuinfo does appear to be more like a file then a pipe:

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

So at this point we need to take a step back and zoom out a bit. We're looking at a particular file but perhaps we should be looking at the filesystem this file resides on. And for this we can use the mount command.

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

OK, so the filesystem type is of type proc. So /proc is a different filesystem type, that's our hint that the files under /proc are special. They're not just your run of the mill files. So let's find out some more info about what makes the proc filesystem special.

Taking a look at mount's man page:

The proc filesystem is not associated with a special device, and when mounting it, an arbitrary keyword, such as proc can be used instead of a device specification. (The customary choice none is less fortunate: the error message `none busy' from umount can be confusing.)

And if we take a look at proc's man page:

The proc file system is a pseudo-file system which is used as an interface to kernel data structures. It is commonly mounted at /proc. Most of it is read-only, but some files allow kernel variables to be changed.

A little bit further down in that same man page:

/proc/cpuinfo

This is a collection of CPU and system architecture dependent items, for each supported architecture a different list. Two common entries are processor which gives CPU number and bogomips; a system constant that is calculated during kernel initialization. SMP machines have information for each CPU. The lscpu(1) command gathers its information from this file.

At the bottom of the man page is a reference to a kernel document which you can find here, titled: THE /proc FILESYSTEM. Quoting from that document:

The proc file system acts as an interface to internal data structures in the kernel. It can be used to obtain information about the system and to change certain kernel parameters at runtime (sysctl).

Conclusions

So what did we learn here? Well given that /proc is referred to as a pseudo filesystem and also a "interface to internal data structures" it's probably safe to assume that items within it are not actual files, but rather just manifestations made to look like files, but are really not.

I'll close with this quote which apparently used to be in a prior version of the man 5 proc from circa 2004 but for whatever reason is no longer included. NOTE: I'm not sure why it was removed since it describes very nicely what /proc is:

The /proc directory on GNU/Linux systems provides a file-system like interface to the kernel. This allows applications and users to fetch information from and set values in the kernel using normal file-system I/O operation.

The proc file system is sometimes referred to as a process information pseudo-file system. It does not contain ``real'' files but rather runtime system information (e.g. system memory, devices mounted, hardware configuration, etc). For this reason it can be regarded as a control and information center for the kernel. In fact, quite a lot of system utilities are simply calls to files in this directory. For example, the command lsmod, which lists the modules loaded by the kernel, is basically the same as 'cat /proc/modules' while lspci, which lists devices connected to the PCI bus of the system, is the same as 'cat /proc/pci'. By altering files located in this directory you can change kernel parameters while the system is running.

Source: The proc pseudo file-system

References

share|improve this answer
1  
Cool, :) this is the first thing I tried as I saw the question: strace -o catcpuproc.txt cat /proc/cpuinfo –  Ketan Mar 27 at 3:18
1  
Nice answer! On linux, if you want to dig deeper, the source for the proc filesystem is in fs/proc in the kernel source. You'll see that there is a fs/proc/cpuinfo.c but, unfortunately, it is rather empty since the heavy lifting is spread out all over arch/ as it is architecture dependent. For a simpler example see fs/proc/uptime.c. By glancing at the file we can guess that uptime_proc_show is the workhorse of what gets us the data we want and we could explore it more by diving into the functions it calls. To understand the seq_file interface and how it is used in procfs see: –  Steven D Mar 27 at 4:08
1  
linux.com/learn/linux-training/… and lwn.net/Articles/22355 (a bit dated) –  Steven D Mar 27 at 4:09
1  
@slm : +1, great answer. But to me, the first hint it's a special file is its size ^^ 0 bytes, yet you can cat lots of things from it (a bit like some pipe files). –  Olivier Dulac Mar 27 at 9:16
    
@OlivierDulac - good point. I've made additional edits based on your feedback. LMK if I can make any further improvements. Thanks. –  slm Mar 27 at 11:49

The answer given by @slm is very comprehensive, but I think a simpler explanation might come from a change in perspective.

In day-to-day usage we can think of files as physical things, ie. chunks of data stored on some device. This makes files like /proc/cpuinfo very mysterious and confusing. However, it all makes perfect sense if we think of files as an interface; a way to send data in and out of some program.

The programs which send and receive data in this way are filesystems or drivers (depending on how you define these terms, that might be too broad or too narrow a definition). The important point is that some of these programs use a hardware device to store and retrieve the data sent via this interface; but not all.

Some examples of filesystems which don't use a storage device (at least directly) are:

  • Filesystems using looked-up or calculated data. Proc is an example, since it gets data from various kernel modules. An extreme example is πfs ( github.com/philipl/pifs )
  • All FUSE filesystems, which handle the data with a regular userspace program
  • Filesystems which transform the data of another filesystem on-the-fly, for example using encryption, compression or even audio transcoding ( khenriks.github.io/mp3fs/ )

The Plan9 OS ( http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs ) is an extreme example of using files as a general programming interface.

share|improve this answer
    
+1 for the Plan9 reference. –  tchrist Mar 29 at 18:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.