ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


FreeBSD Basics

Discovering System Processes

11/15/2000

In the next two articles, I'd like to take a look at processes. This week, we'll see what a process is and how to view information regarding your processes. Next week, we'll look at doing useful things with this process information.

Like any other Unix system, FreeBSD is a multitasking, multiuser operating system. This means that a number of users can each be running a number of programs at the same time. It is the kernel's responsibility to ensure that each of these programs gets a fair turn at your computer's CPU and that each user receives the correct results from their program's execution.

When you start a program, it is loaded into RAM and is called a process, as its instructions need to be processed by the CPU. In order for the kernel to keep track of which programs are running and which user started which program, each process is assigned a process ID, or PID. Usually, the PID will be associated with, and have the same permissions as, the user who started the program and that user's primary group.

Not all programs are started by users; some are started by your FreeBSD system at boot time and are called daemons. Also, some programs will either start other programs or other instances of themselves. The original program is called the parent process, and the other processes are called its child processes.

When you installed FreeBSD, the process filesystem, or procfs, was created for you. If you type:

more /etc/fstab

you should see the following lines:

# Device  Mountpoint  FStype  Options  Dump  Pass#
proc      /proc       procfs  rw       0     0

Also, you may have noticed that this filesystem is always 100% full when you display your free disk space like so:

df

Filesystem    Size   Used  Avail Capacity  Mounted on
procfs        4.0K   4.0K  0B    100%      /proc

This is normal, as the process filesystem is not supposed to contain files created by users; instead, it is read by the ps and w commands so they can display which processes are currently running. Notice that the proc filesystem is mounted on /proc. Let's take a look at the contents of /proc using ls with the C switch to sort the display into columns and the F switch to mark directories with a trailing slash:

cd /proc
ls -CF
./      175/     2072/     301/     315/
../     176/     227/      307/     316/
0/      177/     261/      308/     317/
1/      178/     27/       309/     318/
110/    181/     273/      310/     319/
163/    197/     290/      311/     320/
166/    199/     292/      312/     4/
171/    2/       3/        313/     5/
173/    202/     30/       314/     curproc@

Note that every entry except one is a directory whose name is a number; that number refers to the PID of a running process. The last entry, curproc, is a symbolic link since it ends with the @ symbol. To find out what it is linked to, type:

file curproc
curproc: symbolic link to 2072

It would appear that curproc is a symbolic link to another process. If you do a:

man 5 procfs

you'll read that curproc actually refers to the current process making the lookup request; that is, my original ls command had a PID of 2072.

Now, let's see what type of information is recorded for each of the running processes by viewing the contents of one of these directories:

ls -CF 197
./       ctl     file@    mem     regs
../      dbregs  fpregs   note    rlimit
cmdline  etype   map      notepg  status

These all seem to be regular files except for the symbolic link named file; however, we have no idea what type of data they contain. Let's find out:

file *
cmdline: empty
ctl:     empty
dbregs:  MS Windows COFF Unknown CPU
etype:   empty
file:    symbolic link to /usr/sbin/inetd
fpregs:  data
map:     empty
mem:     empty
note:    empty
notepg:  empty
regs:    data
rlimit:  empty
status:  empty

It doesn't look like we'll be able to open up any of these files ourselves as they don't contain readable text. This makes sense for a filesystem that keeps track of data useful to the kernel. Even though you can't view the data directly, you can use the w and ps commands, which do know how to interpret and display the data contained within these files.

Let's start with the w command:

whatis w
w(1) - display who is logged in and what they are doing
w
10:43AM  up 17:50, 4 users, load averages: 0.00, 0.00, 0.00
USER        TTY    FROM      LOGIN@  IDLE WHAT
genisis     v0     -         9:46AM     - w
genisis     v1     -        Sat04PM  2:02 -csh (csh)
genisis     v2     -        Sat08PM     - -csh (csh)
genisis     v3     -        Sat05PM  2:02 -csh (csh)

The first line displays the current time of day, how long your FreeBSD system has been up, the number of users currently logged in, and the number of jobs in the run queue averaged over 1, 5, and 15 minutes.

The remaining lines show the user's login name, the name of the terminal that user is logged in to, the host from which the user logged in, the time the user logged on, the time since the user last typed anything, and the name and arguments of the current process.

If we use the d switch with the w command, we'll receive a slightly different output, as w will display all the processes that user has running on their terminal, like so:

w -d
10:55AM  up 18:02, 4 users, load averages: 0.00, 0.00, 0.00
USER     TTY      FROM     LOGIN@  IDLE WHAT
         2100                           -csh (csh)
         2104                           _su (csh)
         2235                           w -d
genisis  v0       -          9:46AM   - w -d
         313                            -csh (csh)
genisis  v1       -       Sat04PM  2:14 -csh (csh)
         314                            -csh (csh)
genisis  v2       -         Sat08PM   - -csh (csh)
         315                            -csh (csh)
genisis  v3       -       Sat05PM  2:14 -csh (csh)

The numbers under the TTY column are the PIDs of the processes. If you read the manpage for w, you'll find that it is a good utility to get a quick overview of who is currently logged in to which terminals and what they might be doing; however, it was not intended to provide detailed process usage information, as that is the job of the ps utility. If you simply type:

ps

you'll receive basic information on the processes you have started, like so:

  PID  TT  STAT   TIME    COMMAND
 2100  v0  Ss     0:00.13 -csh (csh)
 2286  v0  R+     0:00.00 ps
  313  v1  Is+    0:00.13 -csh (csh)
  314  v2  Is+    0:00.21 -csh (csh)
  315  v3  Is     0:00.12 -csh (csh)

Reading the output from left to right, the default ps displays the PID, the name and type of the terminal, state, cpu time (including both user and system time), and the associated command for processes started by the user who ran the ps command.

State is a new term which can provide valuable information about your running processes. When reading the state (STAT) column, the first letter indicates the run state of the process. The valid values are:

In my output, I have one running process (the ps command), one c shell that hasn't done anything within the last 20 seconds, and three c shells that haven't done anything in more than 20 seconds. The "+" symbol indicates that three of my processes are foreground processes, and the "s" indicates that four of my processes are session leaders. Don't worry if some of the state information doesn't hold profound meaning for you; some of it won't unless you are a programmer.

Note that the default ps will only show your processes; to view all the user processes running on your computer, use the a switch:

ps -a
  PID  TT  STAT   TIME COMMAND
 2100  v0  Ss     0:00.18 -csh (csh)
 2403  v0  R+     0:00.00 ps -a
  313  v1  Is+    0:00.13 -csh (csh)
  314  v2  Is+    0:00.25 -csh (csh)
  315  v3  Is+    0:00.12 -csh (csh)
  316  v4  Is+    0:00.01 /usr/libexec/getty Pc ttyv4
  317  v5  Is+    0:00.01 /usr/libexec/getty Pc ttyv5
  318  v6  Is+    0:00.01 /usr/libexec/getty Pc ttyv6
  319  v7  Is+    0:00.01 /usr/libexec/getty Pc ttyv7

You may find it more useful to see which users started which commands; to do this, include the u switch:

ps -au
USER      PID %CPU %MEM   VSZ  RSS  TT  STAT STARTED   TIME COMMAND
genisis  2404  0.0  0.2   428  244  v0  R+   12:26PM   0:00.00 ps -au
root      273  0.0  0.4   620  448 con- I+    4:53PM   0:00.02 /bin/sh /usr/loc
root      292  0.0  0.4   624  452 con- I+    4:53PM   0:00.01 /bin/sh /usr/loc
genisis   313  0.0  0.8  1328  944  v1  Is+   4:53PM   0:00.13 -csh (csh)
genisis   314  0.0  0.8  1336  960  v2  Is+   4:53PM   0:00.25 -csh (csh)
genisis   315  0.0  0.8  1328  944  v3  Is+   4:53PM   0:00.12 -csh (csh)
root      316  0.0  0.5   920  628  v4  Is+   4:53PM   0:00.01 /usr/libexec/get
root      317  0.0  0.5   920  628  v5  Is+   4:53PM   0:00.01 /usr/libexec/get
root      318  0.0  0.5   920  628  v6  Is+   4:53PM   0:00.01 /usr/libexec/get
root      319  0.0  0.5   920  628  v7  Is+   4:53PM   0:00.01 /usr/libexec/get
genisis  2100  0.0  0.8  1336  960  v0  Ss    9:46AM   0:00.19 -csh (csh)

I find the output easier to read if I include the c switch as it will only show the name of the command, instead of the path:

ps -auc
USER      PID %CPU %MEM   VSZ  RSS  TT  STAT STARTED   TIME COMMAND
genisis  2414  0.0  0.2   428  244  v0  R+   12:31PM   0:00.00 ps
root      273  0.0  0.4   620  448 con- I+    4:53PM   0:00.02 sh
root      292  0.0  0.4   624  452 con- I+    4:53PM   0:00.01 sh
genisis   313  0.0  0.8  1328  944  v1  Is+   4:53PM   0:00.13 csh
genisis   314  0.0  0.8  1336  960  v2  Ss+   4:53PM   0:00.26 csh
genisis   315  0.0  0.8  1328  944  v3  Is+   4:53PM   0:00.12 csh
root      316  0.0  0.5   920  628  v4  Is+   4:53PM   0:00.01 getty
root      317  0.0  0.5   920  628  v5  Is+   4:53PM   0:00.01 getty
root      318  0.0  0.5   920  628  v6  Is+   4:53PM   0:00.01 getty
root      319  0.0  0.5   920  628  v7  Is+   4:53PM   0:00.01 getty
genisis  2100  0.0  0.8  1336  960  v0  Ss    9:46AM   0:00.21 csh

We're still not seeing all of the processes on this system, though. To do this, include the x switch to display the running daemons; this will be a longer output, so we'll pipe it to the more utility:

ps -aucx |more
USER      PID %CPU %MEM   VSZ  RSS  TT  STAT STARTED   TIME COMMAND
genisis  2417  0.0  0.2   428  244  v0  R+   12:32PM   0:00.00 ps
root        1  0.0  0.2   532  304  ??  ILs  Sat11AM   0:00.06 init
root        2  0.0  0.0     0    0  ??  DL   Sat11AM   0:00.11 pagedaemon
root        3  0.0  0.0     0    0  ??  DL   Sat11AM   0:00.00 vmdaemon
root        4  0.0  0.0     0    0  ??  DL   Sat11AM   0:00.20 bufdaemon
root        5  0.0  0.0     0    0  ??  DL   Sat11AM   0:09.53 syncer
root       27  0.0  2.0 70780 2540  ??  ILs  Sat11AM   0:00.08 mount_mfs
root       30  0.0  0.1   208   92  ??  Is   Sat11AM   0:00.00 adjkerntz
root      110  0.0  0.3   536  368  ??  Is    4:53PM   0:00.03 dhclient
root      163  0.0  0.5   904  608  ??  Ss    4:53PM   0:00.53 syslogd
daemon    166  0.0  0.4   916  556  ??  Is    4:53PM   0:00.01 portmap
root      181  0.0  0.5 263052  576  ??  Is    4:53PM  0:00.00 rpc.statd
root      197  0.0  0.6  1028  764  ??  Is    4:53PM   0:00.02 inetd
root      199  0.0  0.6   956  700  ??  Is    4:53PM   0:00.64 cron
root      202  0.0  1.0  1424 1216  ??  Is    4:53PM   0:00.66 sendmail
root      227  0.0  0.4   876  488  ??  Is    4:53PM   0:00.34 moused
root      273  0.0  0.4   620  448 con- I+    4:53PM   0:00.02 sh
root      292  0.0  0.4   624  452 con- I+    4:53PM   0:00.01 sh
genisis   313  0.0  0.8  1328  944  v1  Is+   4:53PM   0:00.13 csh
genisis   314  0.0  0.8  1336  960  v2  Ss+   4:53PM   0:00.26 csh
genisis   315  0.0  0.8  1328  944  v3  Is+   4:53PM   0:00.12 csh
root      316  0.0  0.5   920  628  v4  Is+   4:53PM   0:00.01 getty
root      317  0.0  0.5   920  628  v5  Is+   4:53PM   0:00.01 getty
root      318  0.0  0.5   920  628  v6  Is+   4:53PM   0:00.01 getty
root      319  0.0  0.5   920  628  v7  Is+   4:53PM   0:00.01 getty
genisis  2100  0.0  0.8  1336  960  v0  Ss    9:46AM   0:00.21 csh
root     2239  0.0  3.6  5012 4512  ??  Ss   10:57AM   0:00.40 perl
root     2240  0.0  3.6  5012 4512  ??  I    10:57AM   0:00.02 perl
root        0  0.0  0.0     0    0  ??  DLs  Sat11AM   0:00.06 swapper

Wow, no wonder the kernel needs to assign PIDs to keep track of what is happening on your FreeBSD system. If you find it hard to remember which column is which, add an h to your switches to force ps to rewrite the column headings on every screen.

You may have noticed that our columns changed when we introduced the u switch; the most notable new columns are %CPU and %MEM. Sometimes you may find it more useful for ps to display the processes by CPU or memory usage, rather than in numerical order. To sort by memory usage, use the m switch; to sort by CPU usage, use the r switch.

ps -m
  PID  TT  STAT   TIME COMMAND
  314  v2  Ss+    0:00.28 -csh (csh)
 2100  v0  Ss     0:00.27 -csh (csh)
  313  v1  Is+    0:00.14 -csh (csh)
  315  v3  Is+    0:00.12 -csh (csh)
 2570  v0  R+     0:00.00 ps -m
ps -r
  PID  TT  STAT   TIME COMMAND
  313  v1  Is+    0:00.14 -csh (csh)
  314  v2  Ss+    0:00.28 -csh (csh)
  315  v3  Is+    0:00.12 -csh (csh)
 2100  v0  Ss     0:00.27 -csh (csh)
 2571  v0  R+     0:00.00 ps -r

The switches I've mentioned are the most commonly used switches for the ps utility; you can read the manpage for ps to see what other switches are available so you can find out which combo of switches tweaks the output to your liking.

When using ps, you will most likely come across processes that you've never heard of before; use the whatis command to see which manpages will shed light on the mystery. For example, being the very curious type, I tried the following:

whatis init syncer adjkerntz inetd portmap rpc.statd
init(8) - process control initialization
syncer(4) - filesystem synchronizer kernel process
adjkerntz(8) - adjust local time CMOS clock to reflect time zone changes and keep current timezone offset for the kernel
inetd.conf(5), inetd(5) - internet super-server
portmap(8) - RPC program,version to DARPA port mapper
rpc.statd(8) - host status monitoring daemon

which kept me busy reading for a while. It should also give you lots to do til next week, when we'll look at what we can do with all of this newfound knowledge.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.


Read more FreeBSD Basics columns.

Discuss this article in the Operating Systems Forum.

Return to the BSD DevCenter.

 

Copyright © 2009 O'Reilly Media, Inc.