Process
Description of a process
A process is a program running in a UNIX system. It communicates with the rest of the system or network by means of syscalls, descriptors or shared memory. A process is in protected memory also called virtual memory because address locations are translated by the kernel from the real physical addresses. A process cannot read the memory of another process owned by another user unless both processes share that memory which needs to be set up by both. Interfaces for reading the memory of another process of the same uid are ptrace and the /proc filesystem.
A process is created by the fork syscall by a parent process. The new process is also called the child. After fork the child retains all memory and descriptors of its parent.
A typical process is composed of text, initialized data, uninitialized data (bss), heap and stack. Because of paging a process' text does not need to be loaded completely into memory but is loaded in chunks called pages when it tries to access an area that hasn't been paged in yet (this causes a page fault to indicate to the kernel that more data is needed). This is called demand paging. When memory pages aren't being used they can be paged out to swap to make room for more memory that other processes may require. When a threshold is reached and processes aren't active for longer periods of time they can be entirely swapped out to disk. This is rather slow and often avoided when possible. Processes can be signal'ed to stop execution, continue execution and to exit including leaving a core file for later analysis.
Each process has a unique pid to identify it and a ppid to identify its parent. Other properties about a process are explained in struct proc in /usr/include/sys/proc.h.
To show all processes in BSD type:
$ ps -auwx
To show all processes in SYSV type:
$ ps -ef
When a process dies it will not be cleaned up completely by the kernel but be set into a zombie state, the parent pid will be signaled with a SIGCHLD signal and it is expected to wait(2) on the zombie child. As soon as this is complete the kernel will clean the process table completely from the zombie process. Orphaned processes that become zombies are waited on by init.
Ending a Process
A user can end a process by killing it. By default the TERM (15) signal is sent. It is wise to send a TERM signal to a process so that it can trap this signal and do possible safe shutdown's of open files or databases. When it is absolutely necessary to immediately kill a process the KILL (9) signal is used, the process terminates immediately without being able to safely shut anything off. Sometimes a process is "in-disk" (state D in a ps listing) meaning it is awaiting i/o from the kernel. In this state a process cannot be killed at all and it may be wedged forever until the next boot of the system.
The latest way to do this is with the pkill command:
$ pkill process
You will have to have proper permission to kill this process. You can optionally include a signal with pkill.
The traditional command to do this is kill(1), which takes the pid as an argument and optionally the signal which is supposed to be sent to the process.
$ kill 324 $ kill -TERM 324 $ kill -KILL 324
Here is a list of signals.
Tracing a Process in BSD
BSD has the ktrace command. With it a processes syscalls can be traced. By default ktrace writes the file "ktrace.out". To switch off tracing a simple "ktrace -C" is used. To view the contents of the tracefile you would use kdump. When you need to trace the child of a process the "-i" flag to ktrace is probably best.
12926 ls CALL stat(0x469b6170,0x7f7fffff7490) 12926 ls NAMI "." 12926 ls RET stat 0 12926 ls CALL open(0x528916,0,0) 12926 ls NAMI "." 12926 ls RET open 3 12926 ls CALL fchdir(0x3) 12926 ls RET fchdir 0 12926 ls CALL open(0x528916,0,0) 12926 ls NAMI "." 12926 ls RET open 4 12926 ls CALL open(0x423e5000,0x4,0) 12926 ls NAMI "." 12926 ls RET open 6 12926 ls CALL fstat(0x6,0x7f7fffff7440) 12926 ls RET fstat 0
Above is a snippet of a traced ls.
It is possible to see what processes are traced with the fstat command where a "tr" flag is displayed with the inode of the trace file.
$ fstat | grep mplayer ... pbug mplayer 11555 wd /usr 8016513 drwx------ r 8192 pbug mplayer 11555 tr /usr 8016941 -rw------- rw 1273886 ...
Tracing a process with strace (Redhat EL9)
strace comes with Redhat Enterprise Linux 9 (3) at least on my vserver system.
[pjp@proteus pjp]$ strace -fo trace.out fire pbug, fire started. Process 11552 attached
This dumps all information into the file trace.out...
[pjp@proteus pjp]$ head trace.out 11551 execve("/home/pjp/bin/fire", ["fire"], [/* 26 vars */]) = 0 11551 uname({sys="Linux", node="proteus.solarscale.de", ...}) = 0 11551 brk(0) = 0x804c000 11551 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fed000 11551 open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) 11551 open("/etc/ld.so.cache", O_RDONLY) = 3 11551 fstat64(3, {st_mode=S_IFREG|0644, st_size=20916, ...}) = 0 11551 old_mmap(NULL, 20916, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fe7000 11551 close(3) = 0
A bunch of files are opened here in the preload (dynamic linker) of system libraries, there is a lot more after the dynamic libraries are loaded.
Debugging a process that's running
gdb allows one to attach to a process. The process should be compiled with debugging symbols (-g flag). The debugger attaches to the process like so:
$ gdb program 1234
Where program is the program that's running (ie. /bin/ls) and 1234 is the pid of the process. As soon as you attach the processes execution stops and isn't resumed until you quit, step through or continue (after perhaps setting a few breakpoints).