The /proc Filesystem

The proc Filesystem

Linux implements a special virtual filesystem called /proc that stores information about the kernel, kernel data structures, and the state of each process and associated threads. Remember that in Linux a thread is implemented as a special type of process. The /proc filesystem is stored in memory, not on disk. The majority of the information provided is read-only and can vary greatly from one version of Linux to another. Standard system calls (such as open , read , etc.) can be used by programs to access /proc files.

Linux provides a procinfo command that generates a formatted display of /proc information. Figure 2.23 shows the default output of this command. As would be expected, there is a variety of command-line options for procinfo (check the manual page $ man 8 procinfo for specifics). Additionally, while most of the files in /proc are in a special format, many can be displayed by using the command-line cat utility. [13]

[13] Do not be put off by the fact that the majority of the files in /proc show 0 bytes when a long listing is donekeep in mind this is a not a true filesystem.

Figure 2.23 Typical procinfo output.

linux$ procinfo Linux 2.4.3-12enterprise (root@porky) (gcc 2.96 20000731 ) #1 2CPU [linux] Memory: Total Used Free Shared Buffers Cached Mem: 512928 510436 2492 84 65996 265208 Swap: 1068284 544 1067740 Bootup: Thu Dec 27 12:31:23 2001 Load average: 0.00 0.00 0.00 >1/85 10791 user : 0:12:34.61 0.0% page in : 7194848 nice : 0:00:15.34 0.0% page out: 1714280 system: 0:16:18.81 0.0% swap in : 1 idle : 21d 20:49:43.68 99.9% swap out: 0 uptime: 10d 22:39:26.21 context : 31669318 irq 0: 94556622 timer irq 8: 2 rtc irq 1: 2523 keyboard irq 12: 15009 PS/2 Mouse irq 2: 0 cascade [4] irq 26: 17046596 e100 irq 3: 4 irq 28: 30 aic7xxx irq 4: 6223833 serial irq 29: 30 aic7xxx irq 6: 3 irq 30: 155995 aic7xxx irq 7: 3 irq 31: 918432 aic7xxx

In the /proc file system are a variety of data files and subdirectories. A typical /proc file system is shown in Figure 2.24.

Figure 2.24 Directory listing of a /proc file system.

linux$ ls /proc 1 1083 20706 4 684 9228 dma loadavg stat 1025 1084 20719 494 7 9229 driver locks swaps 1030 1085 20796 499 704 9230 execdomains mdstat sys 10457 1086 20797 5 718 9231 fb meminfo sysvipc 10458 19947 20809 511 752 9232 filesystems misc tty 10459 2 3 526 758 9233 fs modules uptime 1057 20268 32463 6 759 9234 ide mounts version 10717 20547 32464 641 765 9235 interrupts mtrr 10720 20638 32466 653 778 9236 iomem net 10721 20652 32468 655 780 997 ioports partitions 10725 20680 32469 656 795 bus irq pci 10726 20695 32471 657 807 cmdline kcore scsi 10731 20696 32473 658 907 cpuinfo kmsg self 10736 20704 32474 669 9227 devices ksyms slabinfo

Numeric entries, such as 1 or 1025, are process subdirectories for existing processes and contain information specific to the process. Nonnumeric entries, excluding the self entry, have kernel-related information. At this point, a full presentation of the kernel- related entries in /proc would be a bit premature, as many of them reflect constructs (such as shared memory) that are covered in detail in later chapters of the text. The remaining discussion focuses on the process-related entries in /proc .

The /proc/self file is a pointer (symbolic link) to the ID of the current process. Program 2.10 uses the system call readlink (see Table 2.25) to obtain the current process ID from / proc/self .

Program 2.10 Reading the /proc/self file.

File : p2.10.cxx /* Determining Process ID by reading the contents of the symbolic link /proc/self */ + #define _GNU_SOURCE #include #include #include #include 10 using namespace std; const int size = 20; int main( ){ pid_t proc_PID, get_PID; + char buffer[size]; get_PID = getpid( ); readlink("/proc/self", buffer, size); proc_PID = atoi(buffer); cout << "getpid : " << get_PID << endl; 20 cout << "/proc/self : " << proc_PID << endl; return 0; }

Table 2.25. Summary of the readlink System Call.

Include File(s)

Manual Section

2

Summary

int readlink(const char *path, char *buf, size_t bufsiz);

Return

Success

Failure

Sets errno

Number of characters read

-1

Yes

The readlink system call reads the symbolic link referenced by path and stores this data in the location referenced by buf . The bufsiz argument specifies the number of characters to be processed and is most often set to be the size of the location referenced by the buf argument. The readlink system call does not append a null character to its input. If this system call fails, it returns a 1 and sets errno ; otherwise , it returns the number of characters read. In the case of error the values that errno can take on are listed in Table 2.26.

A wide array of data on each process is kept by the operating system. This data is found in the /proc directory in a decimal number subdirectory named for the process's ID. Each process subdirectory includes

As noted, the cmdline file has the argument list for the process. This same data is passed to the function main as argv . The data is stored as a single character string with a null character separating each entry. On the command line, the tr utility can be used to translate the null characters into newlines to make the contents of the file easier to read. For example, the command-line sequence

linux$ cat /proc/cmdline tr "

linux$ cat /proc/cmdline tr "" " "

" " "

would display the contents of the cmdline file with each argument placed on a separate line. Program 2.11 performs a somewhat similar function. It displays the contents of the command line by accessing the data in the cmdline file of the executing process.

Program 2.11 Reading the cmdline file.

File : p2.11.cxx #include #include #include #include + #include using namespace std; const int size = 512; int main( ){ 10 ostringstream oss (ostringstream::out); oss << "/proc/" << getpid( ) << "/cmdline"; cout << "Reading from file: " << oss.str() << endl; + static char buffer[size]; ifstream i_file; i_file.open(oss.str().c_str()); // open to read i_file.getline(buffer, size, ' '); 20 char *p = &buffer[0]; // ref 1st char of seq do { cout << "[" << p << "]" << endl; p += strlen(p)+1; // move to next location } while ( *p ); // still ref a valid char + return 0; }

In line 11 of the program, a new output stream descriptor for a string ( oss ) is declared. In line 12 the name of the file (using a call to getpid to obtain the process ID) is constructed and written to the string. The specified file is opened and read into buffer . The contents of buffer is parsed and displayed. The processing loop uses the fact that the command-line arguments are separated by a null character to divide the data into its separate arguments. Figure 2.25 shows the output of the program when several arguments are passed on the command line.

Figure 2.25 Program 2.11 output.

linux$ p2.11 this is 1 test Reading from file: /proc/12123/cmdline [p2.11] [this] [is] [1] [test]

EXERCISE

The file environ stores the process's environment variables in a format similar to the content of the cmdline file. Modify Program 2.11 to read and display the contents of the environ file.

EXERCISE

In most versions of Linux the statm file contains a series of integer values separated by blanks. For Red Hat Linux there are seven values in the file. In order, from left to right, these values are (a) program size in KB, (b) memory portion of program in KB, (c) number of shared pages, (d) number of code pages, (e) number of pages of data/stack, (f) number of pages of library, and (g) number of dirty pages. In operating system parlance, a dirty page is one that has been modified (and thus will need to be written back at some time for updating). Write a program that performs an activity that causes a verifiable increase in the number of dirty pages for the process.

Категории