Processes are started with fork(), which duplicates the calling process in it's entirety, memory pages are made copy on write, so nothing is actually duplicated in memory until those memory pages are written to. Each new process has it's own Process ID, memory, I/O descriptors, etc.
fork()
Threads are created with clone() or clone2() which is like fork(), but allows the calling process/thread to determine what aspects of the calling process are either shared or copied -- such as the memory space, FS information, I/O descriptors, signals, etc.
clone()
clone2()
While a process is running it is usually in one of the following states:
SIGSTOP
SIGTSTP
SIGCONT
When a process finishes it returns an exit status code (additional information about resource usage during it's execution may also be available) that is to be given to it's parent process via the wait() system call. Until a process has been waited on (i.e. reaped) it will appear as a zombie. If for some reason the parent is not around, the init process (PID 1) inherits the dead process and reaps it.
wait()
> ps
-eLf
auxm
> pstree
> top > htop
> top
> htop
Memory (+stack, shared memory objects) that is futher divided into:
Virtual Size (VSZ) The amount of memory of all memory objects associated with the process, including non-resident (swapped to disk / over-committed non-used pages) pages and shared memory objects.
Size - The total size of the heap and stack.
Resident Set Size (RSS) - For the most part, the amount of memory that is specifically resident to the particular process (the non-swapped heap + stack.)
File-system information (root fs, cwd, umask)
I/O Descriptors (files, IPC, network objects)
Namespace (hierarchy of mounted filesystems)
Signal handlers
Credentials (man 7 credentials), consisting of:
man 7 credentials
Scheduling priority (niceness, -20(highest) to 19 (lowest))
Resource limits (limit/ulimit)
Processor affinity
Additional Meta information:
man 5 proc
/proc/[0-9]+
/proc/self
/proc/
/fd
/cwd
Signals are like 1/2 bit messages to a process that can have one of the following effects (called dispositions):
Normal signals number from 1 to 31, and many have default actions, SIGKILL (i.e. terminate with extreme prejudice) and SIGSTOP (stop execution) cannot be caught, blocked or ignored.
SIGKILL
> kill [ -signal ] pid [ pid... ]
> kill
-
> killall name
> killall
> pgrep > pkill
> pgrep
> pkill
Each process or set of processes under a specific user ID have a set amount of resource limits that might be modified upward or downward. Some resources can be made unlimited and some can only be modified downward unless you are the super-user:
Normally the resource limits should be modified by the shell builtin limit (c-shells) or ulimit (Bourne shells such as bash.)
limit
ulimit
> prlimit
(tcsh) > limit (bash) > ulimit
(tcsh) > limit
(bash) > ulimit
> nice
> renice
> ionice
-c
-n
class (3) idle Lowest priority (2) best-effort Normal (8 levels, 0 being highest, 7 lowest) (1) realtime Highest (8 levels)
man 5 core
When a program dies due to an error in the program, such as from a segmentation fault (attempting to access memory not allocated to the process,) it may be allowed to dump an image of its memory to a file, called a core dump, which can then be accessed via a debugger, such as gdb to help debug the cause of the fault. This can be very useful to debug a long-running program where one may wish to run the program in the background (such as a daemon) and not wait in a debugger for it to fail.
gdb
The core file will usually be written into the processes current working directory at the time of the program fault.
NOTE: Setuid processes cannot dump core (they create 0 byte corefiles,) unless /proc/sys/fs/suid_dumpable is set. Read man core(5) for other limitations. Be sure that core files generated by privileged processes cannot be access by a normal user as the core file could contain sensitive information, such as hashed passwords, private keys, etc.
/proc/sys/fs/suid_dumpable
man core(5)
(tcsh) > limit coredumpsize unlimited (bash) > ulimit -c unlimited
(tcsh) > limit coredumpsize unlimited
(bash) > ulimit -c unlimited
The above will let processes generate core-dumps for debugging.
#include <stdio.h> int main(void) { char *s = NULL; printf("%s\n", s); /* Dereferences a NULL pointer */ }
> gcc -ggdb -o crash crash.c
> limit coredumpsize unlimited
> ./crash Segmentation fault (core dumped)
> ./crash
Segmentation fault (core dumped)
> gdb ./crash core
...
(gdb) where, etc.
(gdb) where