Process State Only one process can be running on a uniprocessor The scheduler decides rrunniing Processes which of the ready processes to run.
bllocckked orr Creating and using multiple processes rreadyy sslleepiing
A process is ready if it A process is blocked if it could use the CPU immediately. waiting for an event (I/O, signal)
12 13
Fork Fork example
• The fork system call creates a duplicate of the currently int main () running program. { • The duplicate (child process) and the original (parent pid_t pid; process) both proceed from the point of the fork with pid = fork(); exactly the same data. if (pid < 0) { • The only difference is the return value from the fork call. perror("fork()"); } else if (pid > 0) { Process printf("parent\n"); A } else { /* pid == 0 */ Process printf("child\n"); A fork } return 0; Process Ch 5.2 } A1
14 15 Fork: PIDs and PPIDs When fork() fails
• System call: int fork(void) • There is a limit to the maximum number – If fork() succeeds it returns the child PID to the parent and returns 0 to the child; of processes a user can create. – If fork() fails, it returns -1 to the parent (no child • Once this limit is reached, subsequent is created) and sets errno calls to fork() return -1. • Related system calls: – int getpid() – returns the PID of current process – int getppid() – returns the PID of parent process (ppid of 1 is 1)
16 17
fork() properties Fork example • Properties of parent inherited by child: int i; pid_t pid; – UID, GID – controlling terminal i = 5; – CWD, root directory printf("%d\n", i); – signal mask, environment, resource limits pid = fork(); – shared memory segments • Differences between parent and child if (pid > 0) i = 6; /* only parent gets here */ – PID, PPID, return value from fork() else if (pid == 0) – pending alarms cleared for child i = 4; /* only child gets here */ – pending signals are cleared for child printf("%d\n", i);
18 19 Fork Example PID/PPID Example Original process (parent) Child process #include
Ch 5.7 Process Termination wait() Ch 5.6 • Orphan process: • System call to wait for a child – a process whose parent is the init process (PID 1) – pid_t wait(int *status) because its original parent died before it did. • A process that calls wait() can: • Terminating a process: exit() – block (if all of its children are still running) • Every normal process is a child of some parent, a terminating process sends its parent – return immediately with the termination status of a child (if a child has terminated and is waiting for its a SIGCHLD signal and waits for its termination status to be fetched) termination status to be accepted. – return immediately with an error (if it doesn’t have • The Bourne shell stores the termination code any child processes.) of the last command in $?.
22 23 Zombies wait and waitpid • wait() can • A zombie process: – block – return with termination status – a process that is “waiting” for its parent to accept its return code – return with error – a parent accepts a child’s return code by • If there is more than one child wait() returns executing wait() on termination of any children – shows up as Z in ps –a • waitpid can be used to wait for a specific child – A terminating process may be a (multiple) pid. parent; the kernel ensures all of its children • waitpid also has an option to block or not to are orphaned and adopted by init. block
24 25
wait and waitpid Example of wait • waitpid has an option to block or not to block #include
#include
28 29
Exec example exec properties Program X int i = 5; • New process inherits from calling printf("%d\n", i); process: exec("Y"); – PID and PPID, real UID, GID printf("%d\n", i); – controlling terminal – CWD, root directory, resource limits Program Y – pending signals printf("hello\n"); – pending alarms
30 31 exec() Processes and File Descriptors • Six versions exec(): execl(char *path, char *arg0, …, (char *)NULL); • File descriptors are handles to open files. execv(char *path, char *argv[]); • They belong to processes not programs. execle(char *path, char *arg0, …,(char *)NULL, • They are a process’s link to the outside world. char *envp[]); execve(char *pathname, char *argv[], char *envp[]); execlp(char *file, char *arg0, …,(char *)NULL); execvp(char *file, char *argv[]);
32 33
FDs preserved across fork and exec Initializing Unix
init init init init init Prroccessss A Prroccessss B rrunniing fork fd=8 prrogrram X exec exec exec fd=3 init getty login tcsh fork() /u/krueger/bar exec("Y"); /u/krueger/foo Time fd=8 fd=3 • See “top”, “ps –aux” to see what’s running Process C Prroccessss A Process C • The only way to create a new process is to rrunniing program Y duplicate an existing process. Therefore the program Y ancestor of all processes is init with pid = 1 Ch 5.5 • The only way to run a program is with exec 34 35 How csh runs commands How csh runs
csh csh csh Prroccessss rrunniing sshellll duplicate: PID 34 fork() fork fork PID 34 Chiilld exec exec process running shell csh date csh ls process running shell Parrentt PIID 35 Time prroccessss rrunniing sshellll differentiate: PIID 34 exec() • When a command is typed, csh forks and then execs wait for child: Chiilld the typed command. wait() prroccessss rrunniing prrogrram Parrentt PIID 35 • After the fork, file descriptors 0, 1, and 2 still refer to prroccessss rrunniing sshellll terminate: stdin, stdout, and stderr in the new process. PIID 34 exit() • By convention, the executed program will use these Chiilld process terminated descriptors appropriately. signal process terminated PIID 35
36 37