- 58 -

The Pseudo File System

by Kamran Husain

IN THIS CHAPTER

Linux supports the pseudo file system interface to the internal data structures for the kernel. This is your private view of parameters used by the Linux kernel. Using this file system, you can look at the internal data structures for processes and some internal kernel data structures as well. You can get all this information in a "read-only" directory called the /proc directory. You can access a more detailed man page for this information via the following command:

$ man 5 proc

(Don't use man proc because that will give you the man (n) pages for Tcl's proc.) The man page describes the formats for all the outputs in the system. This section will introduce you to some of the more common useful features of /proc. We'll cover how to use these numbers in this chapter.

Let's look at a typical listing of the /proc directory, as shown in Listing 58.1.

Listing 58.1. A typical listing of /proc.

$ ls -l /proc

total 0

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 1

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 13

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 2

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 3

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 3057

dr-xr-xr-x   3 root     nogroup         0 Oct 18 08:30 3963

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 4

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4102

dr-xr-xr-x   3 root     users           0 Oct 18 08:30 4103

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4105

dr-xr-xr-x   3 root     users           0 Oct 18 08:30 4106

dr-xr-xr-x   3 root     users           0 Oct 18 08:30 4107

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4108

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4109

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4110

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4111

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 4125

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 43

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 5

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 5058

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5059

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5437

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5448

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5450

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5454

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 5555

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 6

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 62

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 64

dr-xr-xr-x   3 bin      root            0 Oct 18 08:30 66

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 68

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 7

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 70

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 708

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 72

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 75

dr-xr-xr-x   3 khusain  users           0 Oct 18 08:30 84

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 85

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 86

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 87

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 88

dr-xr-xr-x   3 root     root            0 Oct 18 08:30 89

-r--r--r--   1 root     root            0 Oct 18 08:30 cmdline

-r--r--r--   1 root     root            0 Oct 18 08:30 cpuinfo

-r--r--r--   1 root     root            0 Oct 18 08:30 devices

-r--r--r--   1 root     root            0 Oct 18 08:30 dma

-r--r--r--   1 root     root            0 Oct 18 08:30 filesystems

-r--r--r--   1 root     root            0 Oct 18 08:30 interrupts

-r--r--r--   1 root     root            0 Oct 18 08:30 ioports

-r--------   1 root     root     33558528 Oct 18 08:30 kcore

-r--------   1 root     root            0 Sep 26 20:51 kmsg

-r--r--r--   1 root     root            0 Oct 18 08:30 ksyms

-r--r--r--   1 root     root            0 Oct 18 07:58 loadavg

-r--r--r--   1 root     root            0 Oct 18 08:30 locks

-r--r--r--   1 root     root            0 Oct 18 08:30 meminfo

-r--r--r--   1 root     root            0 Oct 18 08:30 modules

-r--r--r--   1 root     root            0 Oct 18 08:30 mounts

dr-xr-xr-x   2 root     root            0 Oct 18 08:30 net

-r--r--r--   1 root     root            0 Oct 18 08:30 pci

dr-xr-xr-x   2 root     root            0 Oct 18 08:30 scsi

lrwxrwxrwx   1 root     root           64 Oct 18 08:30 self -> 5555

-r--r--r--   1 root     root            0 Oct 18 08:30 stat

dr-xr-xr-x   5 root     root            0 Oct 18 08:30 sys

-r--r--r--   1 root     root            0 Oct 18 08:30 uptime

-r--r--r--   1 root     root            0 Oct 18 08:30 version

Several points of interest can be seen in this listing. First of all, you see numbered directories. These numbers correspond to process IDs for processes that are running on the system when you issue the command. Naturally, your display will be different than that shown in Listing 58.1, because process IDs rarely match on different systems. The second thing to note is that the file sizes are zero. This includes all the subdirectories in /proc. Links, of course, have sizes.

Each of these subdirectories is a "window" into the kernel. On other UNIX-like systems, you have to be able to read /dev/kmem and figure out what your kernel is up to. On those UNIX systems that support /proc (almost all newer ones do), including Linux, you can look at the information conveniently. There is one catch to this convenience, though. In most cases, /dev/kmem is readable only by the root, whereas the /proc tree is readable by all.

Let's look at some of the input you can get from these files.

Looking at Interrupts

The /proc/interrupts directory provides information about the currently used interrupts your Linux kernel is using. Listing 58.2 shows some of the interrupts on my system.

Listing 58.2. Show the interrupts in the system.

$ cat /proc/interrupts

 0: 185693319  timer

 1:   751422   keyboard

 2:        0   cascade

 4:   891729 + serial

 9:   282710   NE2000

10:   375073   NE2000

13:        0   math error

14:  2166148 + ide0

The numbers for the items you see on your screen will most certainly be different. The format of this output is straightforward. The left column is the interrupt number. The number of hits is shown in the middle column, followed by the name of the driver being used.

Listing the IO Ports

The /proc/ioports directory lists all the used IO ports on your Linux machine.

The output from /proc/ioports, coupled with the output from /proc/interrupts, helps you a great deal when you are trying to debug something. Here's an example I ran into while setting up a firewall recently. I had two NE2000 Ethernet cards in the system using interrupts 9 and 10, as shown in Listing 58.2. When the cards were first installed together, neither card worked. Individually, they worked fine. There was an obvious port conflict. I installed both cards and booted the Linux system. To see which ports it was using, I looked at /proc/ioports and saw that both cards were defaulting to the same port. After a CMOS setup, the Linux machine was up in a jiffy. The output from the /proc/ioports now looks as shown in Listing 58.3.

Listing 58.3. The /proc/ioports listing of IO ports on a Linux machine.

$ cat /proc/ioports

0000-001f : dma1

0020-003f : pic1

0040-005f : timer

0060-006f : keyboard

0080-009f : dma page reg

00a0-00bf : pic2

00c0-00df : dma2

00f0-00ff : npu

01f0-01f7 : ide0

0260-0263 : sbpcd

02f8-02ff : serial(auto)

0300-031f : NE2000

0340-035f : NE2000

0378-037f : lp

03c0-03df : vga+

03e8-03ef : serial(auto)

03f0-03f5 : floppy

03f6-03f6 : ide0

03f7-03f7 : floppy DIR

03f8-03ff : serial(auto)

Listing Process Information

There is a large amount of information about a process. Let's look at the information about the process ID 5454 by looking in the /proc/5454 directory. The output is shown in Listing 58.4.

Listing 58.4. The directories under /proc/processID.

$ ls -l /proc/5454

total 0

-r--r--r--   1 khusain  users           0 Oct 18 08:52 cmdline

lrwx------   1 khusain  users          64 Oct 18 08:51 cwd -> [0302]:132748

-r--------   1 khusain  users           0 Oct 18 08:52 environ

lrwx------   1 khusain  users          64 Oct 18 08:52 exe -> [0302]:22524

dr-x------   1 khusain  users           0 Oct 18 08:52 fd

pr--r--r--   1 khusain  users           0 Oct 18 08:52 maps

-rw------    1 khusain  users           0 Oct 18 08:52 mem

lrwx------   1 khusain  users          64 Oct 18 08:52 root -> [0302]:2

-r--r--r--   1 khusain  users           0 Oct 18 08:52 stat

-r--r--r--   1 khusain  users           0 Oct 18 08:52 statm

-r--r--r--   1 khusain  users           0 Oct 18 08:52 status

The command line that invoked the file is shown in /proc/ID/cmdline. Replace the ID with the process ID you are interested in. Get the ID from the output ps ax command. All the arguments are strings separated by zero bytes. These bytes have to be translated to new lines for each argument to be shown separately. The way to see the output is to use this command:

$ cat /proc/5454/cmdline | tr "\000" "\n"

vi

myfiles.txt$

The working environment for a process can be seen via the /proc/environ directory. As with the cmdline output, all zeros have to be translated to "\n" for the output to be meaningful. If you do not do so, all the environment strings will be gelled together in one long string on the output. The command will look a bit like the one shown in Listing 58.5. (Your output will look different than what's shown here.)

Listing 58.5. Listing the working environment for a process.

$ cat /proc/5454/environ | tr "\000" "\n"

LESSOPEN=|lesspipe.sh %s

ignoreeof=10

HOSTNAME=www.ikra.com

LOGNAME=khusain

MINICOM=-c on

MAIL=/var/spool/mail/khusain

TERMCAP=vs|xterm|vs100|xterm terminal emulator (X Window System):am:bs:km:co#80:li#24:ct=\E[3k:ue=\E[m:is=\E[m\E[?1l\E>:rs=\E[m

\E[?1l\E>:eA=\E)0:as=^N:ae=^O:ac=aaffggjjkkllmmnnooqqssttuuvvwwxx:kI=\

E[2~:kD=:kP=\E[5~:kN=\E[6~:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5

=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k0=\E[21~:F1=\E[23~:F2

=\E[24~:kh=\E[H:kH=\EOw:ks=:ke=:te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:ms:pt

:xn:xo:it#8:RA=\E[?7l:SA=\E?7h:bl=^G:cr=^M:ta=^I:cm=\E[%i%d;%dH:le=^H:

up=\E[A:do=\E[B:nd=\E[C:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:DO=\E[%dB:ho=\E[

H:cl=\E[H\E[2J:ce=\E[K:cb=\E[1K:cd=\E[J:sf=\ED:sr=\EM:st=\EH:cs=\E[%i%

d;%dr:sc=\E7:rc=\E8:ic=\E[@:IC=\E[%d@:al=\E[L:AL=\E[%dL:dc=\E[P:DC=\E[

%dP:dl=\E[M:DL=\E[%dM:so=\E[7m:se=\E[m:us=\E[4m:mb=\E[5m:mh=\E[2m:md=\

E[1m:mr=\E[7m:me=\E[m:kb=:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:

TERM=xterm

HOSTTYPE=i386

PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11/bin:/usr/games:.

HOME=/home/khusain

SHELL=/bin/bash

LS_OPTIONS=--8bit --color=tty -F -b -T 0

MANPATH=/usr/local/man:/usr/man/preformat:/usr/man:/usr/X11/man:/usr/openwin/man

LESS=-MM

DISPLAY=:0.0

OSTYPE=Linux

WINDOWID=8388621

OPENWINHOME=/usr/openwin

SHLVL=3

LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:

d=40;33;01:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.at=01;32:

*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;3:*.zip=01;31:*.z=01;

31:*.Z=01;31:*.gz=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=

01;35:*.tif=01;35:=/usr/bin/vi$

Showing Memory Maps for Processes

Other good information about the process is where the sections of the process are loaded in memory. This information is found in the /proc/mmaps directory. Examining the directory for a process whose ID is 5454 gives the output shown in Listing 58.6.

Listing 58.6. Showing memory maps.

$ cat /proc/5454/maps

08048000-0805f000 r-xp 00000000 03:02 22524

0805f000-08061000 rw-p 00016000 03:02 22524

08061000-0806c000 rwxp 00000000 00:00 0

40000000-40005000 rwxp 00000000 03:02 46931

40005000-40006000 rw-p 00004000 03:02 46931

40006000-40007000 rw-p 00000000 00:00 0

40009000-4000b000 r-xp 00000000 03:02 87901

4000b000-4000c000 rw-p 00001000 03:02 87901

4000c000-40085000 r-xp 00000000 03:02 87903

40085000-4008b000 rw-p 00078000 03:02 87903

4008b000-400bd000 rw-p 00000000 00:00 0

bfffe000-c0000000 rwxp fffff000 00:00 0

This is the format of each line in the output:

address permissions offset major:minor inode

The permissions are the same as those for a process--read, write, and execute. The p stands for private section. If a section is shared, you should have s. The offset is the offset within the file. The major and minor numbers correspond to device names for this process, and the inode is the one corresponding to the page.

One of the most common things you are likely to be concerned with while using Linux is how much memory you're chewing up at the moment. To get a snapshot of the current memory usage, you can use the free command or look at /proc/meminfo. The output is simple and easy to understand, as shown in Listing 58.7.

Listing 58.7. Memory information.

$ cat /proc/meminfo



        total:    used:    free:  shared: buffers:  cached:

Mem:  31670272 30707712   962560 15962112  1359872 13742080

Swap: 35090432   307200 34783232

MemTotal:     30928 kB

MemFree:        940 kB

MemShared:    15588 kB

Buffers:       1328 kB

Cached:       13420 kB

SwapTotal:    34268 kB

SwapFree:     33968 kB

Information on Disk Usage

Other interesting statistics for disk usage are available for those whose really need to know how their system is working. Examining these statistics to see how your system is fairing is a fairly reasonable way to look at the behavior of the system. Look at the output from /proc/stat shown in Listing 58.8.

Listing 58.8. Statistics on your system.

$ cat /proc/stat

cpu  7827918 0 697778 186968393

disk 505252 1 0 0

disk_rio 209050 1 0 0

disk_wio 296202 0 0 0

disk_rblk 525758 2 0 0

disk_wblk 592830 0 0 0

page 533561 699895

swap 17961 75

intr 200154670 195494089 644075 0 0 1201601 0 155 0 0 283570 240158

0 0 0 2291022 0

ctxt 11001290

btime 847886750

processes 23920

The only time I really have used this output was to see how a very large sort program was hitting the page count. The pages being swapped in and out of memory are counted off in the display. The disk light never seemed to go off. The number of page swaps jumped up a lot every time I ran the program when I had a mere 8MB of RAM. After an upgrade to 32MB of RAM, and when I was not running the program in an xterm, the number of pages did not jump up so dramatically. The CPU entry lists the time spent in 1/100ths of seconds in user mode, system mode idling, and uptime. The meanings of the cryptic numbers in the rest of the fields are listed in the man pages.

Another item to look at is the /proc/uptime numbers, which list the total number of seconds spent processing and those spent in idle state. These numbers might not be as precise as you want. You should write your own benchmarking routines if you want precise numbers. The output shown here from /proc/uptime is an example:

$ cat /proc/uptime

1954987.45 1869728.55

The second item in the output is the idle time for the CPU. Note how the idle time is almost 100 times the same number as the fourth number for the idle time in the CPU field from the /proc/stat output. They don't match exactly, because the time required between the typing of these two commands (or to collect this information) is not zero.

Determining System Specifications

Through some judicious use of the information in /proc, a process can determine the specifications for the current operating system. It's fairly easy to use this information to provide the status on a running system using scripts. Consider the Perl script shown in Listing 58.9, which provides information about the current processor as an HTML file. A sample output is shown in Listing 58.10.

Listing 58.9. Showing memory maps as an HTML file.

#!/usr/bin/perl

open(CPUINFO,"/proc/cpuinfo") || die "Cannot open it! $! \n";

print << "HTMLHEAD";

<HTML>

<HEAD>

<TITLE> The CPU </TITLE>

</HEAD>

<BODY>

<H1> This server is running on the following processor </H1>

<TABLE BORDER>

<TH> Attribute </TH><TH> Value </TH>

HTMLHEAD

while (<CPUINFO>) {

($p,$v) = split(/:/,$_);

print "<TR><TD>$p</TD><TD>$v</TD></TR>\n";

}

close(CPUINFO);

print "\n</TABLE> </BODY> </HTML>";

Listing 58.10. An HTML file showing memory maps as an HTML file.

<HTML>

<HEAD>

<TITLE> The CPU </TITLE>

</HEAD>

<BODY>

<H1> This server is running on the following processor </H1>

<TABLE BORDER>

<TH> Attribute </TH><TH> Value </TH>

<TR><TD>processor</TD><TD> 0

</TD></TR>

<TR><TD>cpu</TD><TD> 486

</TD></TR>

<TR><TD>model</TD><TD> DX/4-WB

</TD></TR>

<TR><TD>vendor_id</TD><TD> AuthenticAMD

</TD></TR>

<TR><TD>stepping</TD><TD> 4

</TD></TR>

<TR><TD>fdiv_bug</TD><TD> no

</TD></TR>

<TR><TD>hlt_bug</TD><TD> no

</TD></TR>

<TR><TD>fpu</TD><TD> yes

</TD></TR>

<TR><TD>fpu_exception</TD><TD> yes

</TD></TR>

<TR><TD>cpuid</TD><TD> yes

</TD></TR>

<TR><TD>wp</TD><TD> yes

</TD></TR>

<TR><TD>flags</TD><TD> fpu

</TD></TR>

<TR><TD>bogomips</TD><TD> 60.00

</TD></TR>

</TABLE> </BODY> </HTML>

Summary

The pseudo file system provides a great way to look at the internals of the working kernel. The pseudo file system is a useful window into the Linux kernel. You can find a wealth of information in the /proc directory tree. With judicious use, a process can determine the status of other processes in the system. If you are ambitious, you might even write your own version of Microsoft's MSD program for Linux!