410 likes | 616 Views
TDC368 UNIX and Network Programming. Week 2: UNIX process concepts. Camelia Zlatea, PhD Email: czlatea@cs.depaul.edu. UNIX process concepts. Process control primitives fork, exec, exit, wait, waitpid getpid, getppid library functions: system. Course Outline. UNIX basic commands.
E N D
TDC368UNIX and Network Programming Week 2: • UNIX process concepts Camelia Zlatea, PhD Email: czlatea@cs.depaul.edu
UNIX process concepts. Process control primitives fork, exec, exit, wait, waitpid getpid, getppid library functions: system Course Outline
UNIX basic commands • Changing password: • passwd • Information: • date • cal • who • man • Shells • program that handles user interactions • Bourne shell (sh); default prompt is dollar sign $ • Korn shell (ksh); a superset of the Bourne shell • C shell (csh); developed at UC Berkeley, part of BSD version of UNIX; default prompt is the percent sign % File Manipulation: cat file - displays the content of file ls - list a directory cd - change directory mkdir - create a new directory rm file - delete file rm –r file - delete recursively a catalog
Processes Hierarchy PID=0 swapper PID=1 init init process activates a new process and executed a program called getty for each terminal port of the systems getty: displays the login prompt at the assigned terminal waits for user to type userID execute a new program called login PID = x gtty fork - by init exec gtty
Processes Hierarchy PID=0 swapper PID=1 init login: displays the password prompt at the assigned terminal waits for user to type password verifies userID and password executes the user default shell PID = x login fork - by init exec gtty exec login
Processes Hierarchy PID=0 swapper PID=1 init sh: shell displays the prompt ( example $) and is ready to accepts user commands PID = x sh fork - by init exec gtty exec login exec sh
Processes Hierarchy PID=0 swapper PID=1 init fork - by init exec gtty exec login exec sh PID = x sh PID = y ls -l fork - by sh exec ls Example: a shell command is executed
Execution of a Shell command (will explain this in the next slides) [fork] new process [exec] command [wait] shell waits for child process to terminate Displaying process table (process status) (PID= process ID, TTY=terminal. TIME=duration the process is running, COMMAND=name of the command…) ps ps –al Sequential execution of processes using shell operator semicolon ; ps ; ls Timing a delaying of a process sleep 20 --- delays the shell for 20 seconds sleep 120 ; echo “I am awake!” Shell Processes
Shell does not wait for child process to complete Returns prompter immediately shell: [fork] [fork] [exec] shell child exits immediately after the second [fork], returns prompter shell grand-child [exec] the command in background it is adopted by process init when user logout the background process is terminated sleep 30 & (sleep 120 ; echo “I am awake!”)& The command nohup causes the background process to be immune to terminating signals nohup (sleep 120 ; echo “I am awake!”)& and then logout the command process will continue execution in background where is the echo output displayed, since the process is no longer associated with any terminal? The output is automatically save to nohup.out Background Processes
Terminating a process • The kill command • kill command sends a termination signal to the specified process, with the given PID • Signal is an asynchronous event (identified by an integer number) • Signals 1 to 15 are implemented on the majority of UNIX systems • SIGTERM = 15 (normal termination) • SIGKILL=9 (forced termination) • Example: • sleep 30& • ps PID TTY TIME COMMAND 24000 tty001 0:05 csh 24001 tty001 0:00 sleep 30 24002 tty001 0:02 ps • kill –9 24001
Process - system support Fork system call Process states Exec system call Exit function Background processes Parent-Child Synchronization (wait) UNIX Processes
pid_t pid; pid = fork(); if (pid ==-1) { /* fork failure, no more entries in process table*/ } else if (pid==0){ /*child process*/ } else { /* parent process */ } Fork - System Call
The user process calls fork(); Store system call parameters arguments, return address, local variables) into the user stack. Call corresponding kernel service execution of a trap instruction In kernel space save: parameters, return address and local variables for kernel routine Execute kernel routine Normal Return cleans-up kernel stack switch from kernel to user mode Fork - System Call
Successful return from system call: parent and child processes: share same text segment identical data segments identical user & kernel stack segments same user structure parent normal return restores return address from user stack child “pseudo return” restores same return address as the parent from its user stack Fork - System Call
Parent Process Child Process File Table text data stack I-node Table Open Files Current Directory text data stack Open Files Current Directory
Initiated - fork() Ready-to-Run in ready queue for CPU access Running process quantum Blocked sleep(n); /* deterministic delay */ pause(); /* non-deterministic delay */ Terminated exit(int status); Shell command: ps [options] Process States
Process Model New created wakeup Ready Quantum Expired dispatch Blocked/ Suspended Running User Mode sleep exit System Call Interrupt Return Running Kernel Mode Zombie Terminated Interrupt Interrupt return
Process Image Map Process Table Process Image Proc. n Proc. 1 Text/Code Segment Data Segment Stack Segment Process Control Block
User mode processes in use mode can access their own instructions and data; NOT kernel or other process’s code or data Kernel mode process can access system(kernel) code and data and user addresses Kernel is part of each process Kernel executes on behalf of the process P1 P2 P3 P4 OS HW Kernel Mode User Mode K K U U
#include <sys/types.h> #include <unistd.h> pid_t getpid(void); /* get current process ID */ pid_t getppid(void); /* get ID of the parent of the process */ Process information
pid_t pid; static int x; x=1; pid = fork(); if (pid < 0 ) {perror(“fork failure”)} else if (pid==0) x++; else x--; printf(“process %d: x=%d\n”, getpid(), x); What value(s) are printed for variable x?
#include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { fork(); printf(“A\n”); fork(); printf(“B\n”); fork(); printf(“C\n”); } Comment on the above program output.
#include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { int i; for (i=1; i<=3; i++) { fork(); printf(“PID=%d i=%d\n”, getpid(), i); } printf(“PID=%d i=%d\n”, getpid(), i); } Comment on the above program output.
#include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { int i; for (i=1; i<=3; i++) { if (fork()==0) break; printf(“PID=%d i=%d\n”, getpid(), i); } printf(“PID=%d i=%d\n”, getpid(), i); } Comment on the above program output.
#include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { int i; for (i=1; i<==3; i++) { if (fork()>0) break; printf(“PID=%d i=%d\n”, getpid(), i); } printf(“PID=%d i=%d\n”, getpid(), i); } Comment on the above program output.
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <string.h> void main(void) { static char buf[2]; if (fork()==0) strcpy(buf,”A\n”); else strcpy(buf,”B\n”); sleep(10); write(1,buf,sizeof(buf)); } Comment on the above program execution
#include <unistd.h> int execl(const char *file, const char arg0, .. , const argn); int execv(const char *file, char *argv[]); the process executes the the binary code from file if failure return -1 if success does not return Exec - System Call
File test1.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { int i; for (i=1; i<=3;i++) if (fork()==0) { /* process child */ execv(“/bin/ps”,”ps -el”); } else { /* process partent */ printf(“Parent: %d\n”,getpid()); } } %cc -o test1 test1.c % test1
File test2.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { int i; for (i=1; i<=3;i++) if (fork()==0) { /* process child */ execv(“child”,”child”); } else { /* process partent */ printf(“Parent: %d\n”,getpid()); } } %cc -o test2 test2.c
File child.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> void main(void) { pid_t pid; printf(“Parent: %d\n”,getpid()); sleep(30); } %cc -o test2 test2.c %cc -o child child.c %test2
#include <stdlib.h> void exit(int status); status - parameter returned to parent process status=0 - normal termination status# - abnormal termination Effects: close all open file descriptors notifies the parent (by signal) return status info to parent if parent no longer exists then PPD:=1 (is adopted by process init) Exit - Function Call
#include <unistd.h> void _exit(int status); status - process exit status code status=0 - normal termination status#0 - abnormal termination Effects: terminates a process closes all open file descriptors De-allocates all process data and stack segment process becomes a zombie (it is no longer scheduled to run) init process clean up process table slot _exit - System Call
#include <iostream.h> #include <unistd.h> int main() { cout << "Test for _exit" << endl; _exit(0); return 0; } % CC -o test test.c; test Test for _exit % echo $status 0 _exit - System Call
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); returns -,1 if failure (check errno) no unwaited-for child process interrupt signal returns the child PID, is success synchronization: parent waits for a child to terminate if more child-processes, waits for any Wait - System Call
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t p, int *status, int opt); Return value - a child process ID or -1 Argument pid_t p - a child PID -1 waits for any child (same as wait) 0 waits for any child in same group w/ parent >0 waits for child process with this PID=p <-1 waits for any child with GID = |p| Waitpid - System Call
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t p, int *status, int opt); Options values WNOHANG - do not block if status cannot be obtained WNOWAIT - keep process in wait status WUNTRACED - wait any stopped child process Waitpid - System Call
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> void main(void) { pid_t pid; int i, status; for (i=1; i<=3;i++) if (fork()==0) execv(“child”,”child”); else printf(“Parent: %d\n”,getpid()); while (pid = wait(&status) && pid!=-1) printf(“Child %d is done\n”,getpid()); exit(0); } Parent-Child Process Synchronization
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> void main(void) { pid_t pid[3], p; int i, status; for (i=0; i<=3;i++) if ((pid[i]=fork())==0) execv(“child”,”child”); else printf(“Parent: %d\n”,getpid()); for(i=0;(p=waitpid(pid[i], &status,0)&&p!=-1;i++) if (p!=-1) && (errno==EINTR) printf(“Signal Caught: %s\n”,strerrno(errno)); exit(0); } Parent-Child Process synchronization (by priorities)
#include <stdlib.h> int system(const char* cmd); “system” function User program: system(“ps -e”); System calls actions: fork(); //process creation service execl(“/bin/ps”, “ps -e”); //code execution