The /proc File System
Werner Klauser
The /proc file system (procfs) is an example of a virtual file system used by several UNIX operating systems, including Sun's Solaris, Linux, OpenBSD, and AT&T's UNIX on an NCR system. No official standards regulate the /proc file system. This article provides a brief history of /proc and its implementation on Sun's Solaris 2.5 and Solaris 2.6 operating systems, as well as a few hints about how /proc can be used to solve various system administration problems.
History
The concept of /proc was first introduced by Tom Killian in the research Eight Edition UNIX system and was first written up in a paper: "Process as Files" in the Proceedings of the USENIX Association Summer Conference held in Salt Lake City, June 1984. The early version was essentially a ptrace(2) replacement with the important advancement that the address space of the process could be examined and modified using the read(2) and write(2) system calls rather than the clumsy ptrace(2) one-word-at-a-time interface.
Roger Faulkner and Ron Gomes ported the research version of /proc to SVR4 and provided an easier viewing and access method of the active processes. They presented their work in another USENIX paper: "The Process File System and Process Model in UNIX System V" in the Proceedings of the USENIX Association Winter Conference held in Dallas, TX, January 1991. At that time, Roger Faulkner was with Sun Microsystems and Ron Gomes with AT&T Bell Laboratories. As described in that paper, future work was intended to restructure /proc from a flat file system into a directory hierarchy describing a process. That work was undertaken with Sun's Solaris 2.6.
/proc in Solaris 2.5
What first appears to be a normal file system beginning at /proc and containing large-sized files having the same names as the process IDs of the currently running processes is, in effect, an illusion. They do not occupy disk space - they exist in the working memory and the used swap space. The files contain information that the ps(1) command can show us. The contents of these files and how they are addressed will be discussed in more detail, as will the changes between Solaris 2.5 and Solaris 2.6.
Process Tools
Process tools found in /usr/proc/bin are similar to some options of the ps(1) command, except that the output provided by these tools is much more detailed. In general, the process tools:
- Provide control over processes, allowing users to stop or resume them.
- Display more details about processes, such as fstat(2) and fcntl(2) information, working directories, and trees of parent and child processes.
An explanation of some of the more interesting tools follows.
Tools that control processes:
pstop pid - stops the process
pstart pid - restarts the process
pwait [-v] pid - waits for the processes to end
A practical usage is to stop a process that is using too much CPU power and then restart it during noon time while everybody's out for lunch. Rather then starting another job that also uses a lot of CPU power, let pwait(1) inform you when the CPU-heavy job has finished.
$ /usr/proc/bin/pwait <pid_of_heavy_job1> ; heavy_job2
Tools that display process details:
pfiles pid - fstat(2) and fcntl(2) information for open files
pldd pid - dynamic libraries linked into each process
psig pid - signal actions
ptree pid - process trees containing specific pids of fathers and children
pwdx pid - current working directory
Have you ever wondered who is reading or writing a certain file? All you need is to find out the file's inode, and then you can use pfiles(1) to examine the running process to see which process(es) is using the file. Be certain to run the following command as root, because you need to examine all the system's processes. You must be root to do this.
# ls -i theFile
34277 theFile
# cd /proc
# /usr/proc/bin/pfiles * view
search for "ino:34277"
#
/usr/proc/bin/ptree(1) will give you a useful display of the ancestors and children of the desired process. For example:
$ ps
PID TTY TIME CMD
16149 pts/6 0:05 loggerTest
15766 pts/6 0:00 ksh
$ /usr/proc/bin/ptree 15766
178 /usr/sbin/inet -s
15763 in.rlogind
15765 login -d /dev/pts6 -r sunshine.klauser.ch
15766 -ksh
16149 bin/loggerTest
16769 /usr/proc/bin/ptree 15766
$
If you're having problems unmounting a CD-ROM and you're certain some process is sitting on it, it's no problem for pwdx(1) to find out who the culprit is.
# cd /proc
# /usr/proc/bin/pwdx * grep \/cdrom
2397: /cdrom/sunsolve_3_0_7
# ps -ef | grep 2397
root 2397 2357 0 Mar 09 pts/5 0:00 ksh
root 2588 2397 0 10:24:29 pts/5 0:00 /bin/sh ./sunsolve
root 2652 2370 0 10:26:10 pts/3 0:00 grep 2397
#
It's amazing how these proc(1) tools can help solve those little but messy problems!
Coding Example
Beginning a program with main(int argc, char *argv[]) and then looking at argv[0] will give you the name of how the program was called to execute it. But how does the ps(1) command get the process IDs and the names belonging to these process IDs?
The system command getpid(2) returns the process's ID. But now that you have its ID, what do you do? This is where the /proc file system comes into use. Although these files only exist in a virtual world, they are readable. So, all you need to do is execute a simple open.
#include <stdio.h>
#include <fcntl.h> /* file control option */
#include <unistd.h> /* symbolic constants */
main(int, char *argv[])
{
int ifd; /* file descriptor */
char sFilename[16];
(void) sprintf(sFilename, "/proc/%d", getpid() );
ifd = open(sFilename, O_RDONLY);
(void) fprintf(stderr, "file = %s, file descriptor = %d\n",
sFilename, ifd);
(void) close(ifd);
return(0);
}
Note that if you look at the files in /proc with ls(1), you will have the impression that their names are always five digits. That means if the process's ID is less than 10,000, it must be left-padded with zeros. However, you do not need to take this into account. For example, opening /proc/123 has the same effect as opening /proc/00123. Now that is what I call one of the hidden surprises of a virtual file system. We only want information about the process, so its corresponding file is opened for reading only. But, just opening and closing the virtual file doesn't help us too much. We need to do a bit more.
So, we add the following lines to the above example:
#include <sys/procfs.h> /* process file system info */
....
struct prpsinfo tPrpsinfo; /* ps(1) process information */
....
(void) ioctl(ifd, PIOCPSINFO, &tPrpsinfo);
(void) fprintf(stderr, "processname = %s\n",
tPrpsinfo.pr_fname);
Now the process name is printed out onto stderr.
The include file <sys/procfs.h> introduces our code example to the /proc file system. It includes, among other things, the variable type struct prpsinfo, which is a structure containing process information. Its element pr_fname is the name of the process. It also contains the defined PIOCPSINFO, which gets us ps(1) information. Using PIOCUSAGE and a variable of type struct prusage can provide information concerning the process's usage of computer resources. This must be what sar(1) uses. Do take a look at this include file found in the /usr/include/sys directory.
Solaris 2.6 Changes
The previous flat /proc file system has been restructured into a directory hierarchy that contains additional subdirectories for state information and control functions. Although the flat files no longer exist and are now directories, you can still open them as flat files just as in Solaris 2.5. Another virtual file system surprise!
Summary
As you can see, using /proc and its tools is quite easy and provides information that is otherwise difficult to access. By treating processes as files, procfs enables files to be opened and manipulated in much the same manner as conventional files. This elegant and very UNIX-like approach allows you to gain information about the processes in a straightforward way.n
About the Author
Werner Klauser is an independent UNIX consultant working near Zurich, Switzerland. While not paragliding, enjoying his girls, or roarin' around on his Harley chopper, he can be reached at klauser@klauser.ch or via his Web page www.klauser.ch .
|