The /proc by-process-ID directories

Updated: May 06, 2022

In the main portion of this appendix, we'll look at the format, contents, and functions you can use with the remainder of the /proc filesystem.

You may wish to have the <sys/procfs.h>, <sys/syspage.h>, and <sys/debug.h> header files handy — I'll show important pieces as we discuss them.

A casual ls of /proc yields something like this, right now on my system:

# ls -F /proc
1/          12292/      3670087/    6672454/    950306/
1011730/    2/          3670088/    6676553/    950309/
1011756/    3/          393228/     7/          950310/
1011757/    344077/     405521/     7434315/    950311/
1011760/    344079/     4105/       7462988/    950312/
1011761/    344080/     442378/     7467085/    950313/
1011762/    344083/     45067/      7499854/    950314/
1011764/    3551288/    466965/     770071/     950315/
1011769/    3551294/    471062/     8/          950318/
1011770/    3571775/    479246/     815133/     950319/
1011773/    360468/     4886602/    831519/     boot/
1015863/    3608627/    5/          831520/     dumper#
1036347/    3608629/    548888/     868382/     self/
1040448/    3629116/    593947/     868387/
1044547/    3629121/    6/          868388/
1044548/    3649602/    622620/     950298/
1093686/    3649605/    626713/     950305/

We've discussed the boot entry above. The dumper entry is a hook for dumper (the system core dump utility). Finally, self is a short-form for the current process (in this case, ls).

The individual numbered directories are more interesting. Each number is a process ID. For example, what is process ID 4105? Doing the following:

# pidin -p4105
     pid tid name               prio STATE       Blocked
    4105   1 sbin/pipe           10o RECEIVE     1
    4105   2 sbin/pipe           10o RECEIVE     1
    4105   4 sbin/pipe           10o RECEIVE     1
    4105   5 sbin/pipe           10o RECEIVE     1

shows us that process ID 4105 is the pipe process. It currently has four threads (thread IDs 1, 2, 4 and 5 — thread ID 3 ran at some point and died, that's why it's not shown).

Within the /proc directory, doing a:

# ls -l 4105
total 2416
-rw-------  1 root      root        1236992 Aug 21 21:25 as
-rw-------  1 root      root              0 Aug 21 21:25 cmdline
-rw-r--r--  1 root      root              0 Aug 21 21:25 ctl
-rw-------  1 root      root              0 Aug 21 21:25 exefile
-rw-------  1 root      root              0 Aug 21 21:25 mappings
-rw-------  1 root      root              0 Aug 21 21:25 pmap
-rw-------  1 root      root              0 Aug 21 21:25 vmstat

shows us (among others) a file called as (not in the sense of “as if...” but as an abbreviation for address space). This file contains the addressable address space of the entire process. The size of the file gives us the size of the addressable address space, so we can see that pipe is using a little under one and a quarter megabytes of address space. The ctl file is for issuing devctl() commands, as we'll see later

To further confuse our findings, here's:

# pidin -p4105 mem
 pid tid name           prio STATE       code  data        stack
4105   1 sbin/pipe       10o RECEIVE       16K  148K  4096(132K)
4105   2 sbin/pipe       10o RECEIVE       16K  148K  4096(132K)
4105   4 sbin/pipe       10o RECEIVE       16K  148K  4096(132K)
4105   5 sbin/pipe       10o RECEIVE       16K  148K  4096(132K)
        libc.so.5      @b0300000         312K   16K

If you do the math (assuming the stack is 4096 bytes, as indicated) you come up with:

16 KB + 148 KB + 4 x 132 KB + 312 KB + 16 KB

Or 1020 KB (1,044,480 bytes), which is short by 192,512 bytes.

You'll notice that the sizes don't match up! That's because the as file totals up all the segments that have the MAP_SYSRAM flag on in them and uses that as the size that it reports for a stat(). MAP_SYSRAM can't be turned on by the user in mmap(), but it indicates that the system allocated this piece of memory (as opposed to the user specifying a direct physical address with MAP_PHYS), so when the memory no longer has any references to it, the system should free the storage (this total includes memory used by any shared objects that the process has loaded). The code in pidin that calculates the pidin mem sizes is, to put it nicely, a little convoluted.