Process Part3
Contents
Orphan Process
In the previous section we saw that a parent can create a child process. What happens if the parent exits after creating the child process. The child process does not die. Now we know that each process in Linux has a parent except the init process which is the first process. If the parent process dies then the child process is "adapted" by the init process whose id 1. We can illustrate this by the following program. The below program uses "fork" to create the child process.File: orphan1.c
// A C program to demonstrate Zombie Process. // Child becomes orphan after 10 seconds // when parent process exits. #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main() { // Fork returns process id // in parent process pid_t child_pid = fork(); // Parent process if (child_pid > 0) { printf("\n In the parent process. Waiting for 10 seconds.\n "); fflush(stdout); sleep(10); printf("\n Parent process has exited.\n "); fflush(stdout); } // Child process else { printf("\n In the child process. Waiting for 60 seconds. \n"); fflush(stdout); sleep(60); printf("\n Child process exiting.\n"); fflush(stdout); } return 0; }
We open 2 terminal windows. We run the program in the first terminal window and monitor the processes in the second terminal window.
[amittal@hills process]$ gcc orphan1.c -o orphan [amittal@hills process]$ ./orphan1 In the parent process. Waiting for 10 seconds. In the child process. Waiting for 60 seconds. Parent process has exited. [amittal@hills process]$ Child process exiting. [amittal@hills process]$ Initially both the parent and child processes are running. The one with id of "3718893" is the parent. amittal 3718893 3718463 0 16:31 pts/92 00:00:00 ./orphan1 amittal 3718894 3718893 0 16:31 pts/92 00:00:00 ./orphan1 amittal 3718899 3718490 0 16:31 pts/110 00:00:00 grep --color=auto orphan After 10 seconds the parent process has exited. The child process is adapted by the init process and it's parent id becomes 1. [amittal@hills process]$ ps -aef | grep "orphan" amittal 3718894 1 0 16:31 pts/92 00:00:00 ./orphan1 amittal 3718906 3718490 0 16:32 pts/110 00:00:00 grep --color=auto orphan After 60 seconds the child process has exited. [amittal@hills process]$ ps -aef | grep "orphan" amittal 3718935 3718490 0 16:33 pts/110 00:00:00 grep --color=auto orphan
Signals and Traps
A signal ( as it's name implies ) is an interrupt sent to a process notifying it that an important event has occurred. The process may ignore the signal or act upon it. We may have been using signals without being aware of it. Anytime we do "Ctrl-C" or use the "kill" command we are using a signal. Let's try some basic examples.File: sig1.sh
echo "About to sleep" sleep 60 echo "End of sleep"
[amittal@hills signals]$ chmod 777 sig1.sh [amittal@hills signals]$ ./sig1.sh About to sleep ^C[amittal@hills signals]$The "sig1.sh" gets executed and basically sleeps for 60 seconds. We hit the "Ctrl-C" and that causes the INT signal to be sent to the process which causes the process to terminate. The below is another example. We execute a simple process that sleeps for 60 seconds in the backgroud.
[amittal@hills signals]$ sleep 60& [1] 3792814 [amittal@hills signals]$ ps -aef | grep "sleep" amittal 3792814 3776942 0 13:54 pts/54 00:00:00 sleep 60 amittal 3792824 3776942 0 13:55 pts/54 00:00:00 grep --color=auto sleep We send the 9 ( SIGKILL ) signal to the process and that effectively kills it. The format of the "kill" command is "kill signal processid" . [amittal@hills signals]$ kill -9 3792814 [amittal@hills signals]$ ps -aef | grep "sleep" amittal 3792828 3776942 0 13:55 pts/54 00:00:00 grep --color=auto sleep [1]+ Killed sleep 60 [amittal@hills signals]$We can use numbers of their word equivalents for sginals. We can get a listing of the different signals on the hills server with the "kill -l" command.
[amittal@hills signals]$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Using the "SIGKILL" instead of the number 9.
[amittal@hills signals]$ sleep 60& [1] 3794171 [amittal@hills signals]$ kill -SIGKILL 3794171 [amittal@hills signals]$ ps -aef | grep "sleep" amittal 3794173 3776942 0 14:27 pts/54 00:00:00 grep --color=auto sleep [1]+ Killed sleep 60 [amittal@hills signals]$When a process receives a signal it performs a default action. So doing a Ctrl-C sends an interrupt signal which terminates the process. Let's say we did not want this. We can override this behavior.
File: trap1.sh
trap '' 1 2 echo "About to sleep" sleep 60 echo "End of sleep"In the above code we have the "trap" command. We can list some signals that will be trapped. Amongst those signals is the interrupt ( Ctl-C ) signal. The ' ' after trap means that no action is to be taken.
Hitting Ctrl-C does not terminate the process. [amittal@hills signals]$ ./trap1.sh About to sleep ^CWe can also have an action in the trap command.
File: trap2.sh
trap 'rm data.txt' 1 2 echo "About to sleep" sleep 60 echo "End of sleep"In the above we have the command to remove a file if the interrupt signal is received. We create a file called "data.txt" in our folder where the file "trap2.sh" resides. If we hit "Ctrl-C" then the file is removed.
[amittal@hills signals]$ ls data.txt sig1.sh trap1.sh trap2.sh [amittal@hills signals]$ ./trap2.sh About to sleep ^CEnd of sleep The trap command is executed and the file "data.txt" is removed. [amittal@hills signals]$ ls sig1.sh trap1.sh trap2.shNote we cannot trap the signal 9 as that means we won't be able to kill the process at all which can be a problem for runaway processes.
Pipes
We have been using pipes as commands on the shell. A pipe is a series of processes conncect by a pipe. Example:The output of "ls" goes to a pipe and the next process ( "grep" ) uses this as input. If there was another pipe after grep it will receive the output of "grep". [amittal@hills process]$ ls | grep "zomb" zombie zombie1 zombie1.cThe above is a use of unamed pipes. We can also have a filesystem object called named pipe. We create this with the "mkfifo" command.
On one terminal window create a named pipe called "mypipe" . Then the output of ls is redirected to "mypipe". The function will hang till the data is read. [amittal@hills cs260a]$ cd process [amittal@hills process]$ mkfifo mypipe [amittal@hills process]$ ls a.out exec3 f3.c zombie zombie.c exec1 exec3.c mypipe zombie1 zomibe1 exec1.c f1.c orphan zombie1.c exec2 f2 orphan1 zombie2 exec2.c f2.c orphan1.c zombie2.c [amittal@hills process]$ ls > mypipe On another terminal go the same folder. If we are in a different folder then the command will not be able to find the file "mypipe" . [amittal@hills cs260a]$ cat < mypipe -bash: mypipe: No such file or directory [amittal@hills cs260a]$ cd process/ [amittal@hills process]$ cat < mypipe a.out exec1 exec1.c exec2 exec2.c The mypipe is a file and if we do a "ls -l" on it we will see the character "p" signifying that it is of type "p". We can also remove it using the normal "rm" command. [amittal@hills process]$ ls -l my* prw------- 1 amittal csdept 0 Apr 14 23:36 mypipe [amittal@hills process]$ rm mypipe [amittal@hills process]$ ls -l my* ls: cannot access 'my*': No such file or directoryThe concept of named pipes can be used by multiple processes to communicate with each other. One process writes to the pipe while the other process can read from it.
ulimit
There are limits on what resources a process can use. These limits can be managed by a tool called "ulimit". To see the current limits we can do "ulimit -a" ( the a is for all limits). On the hills server we get.[amittal@hills process]$ ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 46959 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 46959 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [amittal@hills process]$The "file size" is "unlimited". If this value was 0 then this user cannot create a file. We also have limits for virtual memory, cpu time, the number of open files a process can have. The CPU time is the number of seconds allowed for a process. If we give a value after the option then that sets the new limit.
[amittal@hills process]$ ulimit -t 10 By default only the soft limits are output. [amittal@hills process]$ ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 46959 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) 10 max user processes (-u) 46959 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [amittal@hills process]$In the above we set the cpu time limit to be 10 seconds and then list the limits to check that the limit has been set. This limit is only valid for this session. If we open another putty session we will not see this change. We have hard limits and soft limits. The soft limit is the value that we can change and the hard limit is the absloute upper limit. The soft limit cannot be higher than the hard limit. We can find out the hard and soft limits with the command:
Soft limits [amittal@hills process]$ ulimit -aS core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 46959 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) 10 max user processes (-u) 46959 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [amittal@hills process]$ ulimit -aH core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 46959 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 262144 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) 10 max user processes (-u) 46959 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [amittal@hills process]$ Hard Limits [amittal@hills process]$ ulimit -aH core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 46959 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 262144 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) 10 max user processes (-u) 46959 virtual memory (kbytes, -v) unlimited file locks (-x) unlimitedThee is a configuration file that keeps these limits. It is "/etc/security/limits.conf". We can view the output of this file. on the hills server.
[amittal@hills ~]$ cat /etc/security/limits.conf # /etc/security/limits.conf # #This file sets the resource limits for the users logged in via PAM. #It does not affect resource limits of the system services. # #Also note that configuration files in /etc/security/limits.d directory, #which are read in alphabetical order, override the settings in this #file in case the domain is the same or more specific. #That means for example that setting a limit for wildcard domain here #can be overriden with a wildcard setting in a config file in the #subdirectory, but a user specific setting here can be overriden only #with a user specific setting in the subdirectory. # #Each line describes a limit for a user in the form: # #All the entries are commented out. That means the default values are used.# #Where: # can be: # - a user name # - a group name, with @group syntax # - the wildcard *, for default entry # - the wildcard %, can be also used with %group syntax, # for maxlogin limit # # can have the two values: # - "soft" for enforcing the soft limits # - "hard" for enforcing hard limits # # - can be one of the following: # - core - limits the core file size (KB) # - data - max data size (KB) # - fsize - maximum filesize (KB) # - memlock - max locked-in-memory address space (KB) # - nofile - max number of open file descriptors # - rss - max resident set size (KB) # - stack - max stack size (KB) # - cpu - max CPU time (MIN) # - nproc - max number of processes # - as - address space limit (KB) # - maxlogins - max number of logins for this user # - maxsyslogins - max number of logins on the system # - priority - the priority to run user process with # - locks - max number of file locks the user can hold # - sigpending - max number of pending signals # - msgqueue - max memory used by POSIX message queues (bytes) # - nice - max nice priority allowed to raise to values: [-20, 19] # - rtprio - max realtime priority # #
# #* soft core 0 #* hard rss 10000 #@student hard nproc 20 #@faculty soft nproc 20 #@faculty hard nproc 50 #ftp hard nproc 0 #@student - maxlogins 4 # End of file [amittal@hills ~]$
-
These "default" limits are applied by:
- The Linux kernel at boot time (to the init or systemd process),
- Inheritance, from the parent process' limits (at fork(2) time),
- PAM when the user session is opened (can replace kernel/inherited values),
- Systemd, especially to the processes it manages,
- The process itself (can replace PAM & kernel/inherited values, see setrlimit(2)).
The "-n" is the number of open files. The hard value from above is 262144. If we try to change the hard limit we will get an error. [amittal@hills limits.d]$ ulimit -Hn 262145 -bash: ulimit: open files: cannot modify limit: Operation not permitted Without the "H" or the "S" the ulimit with a value will set both the hard and soft limits.