Princeton University Computer Science 217: Introduction to Programming Systems. Process Management

Similar documents
Princeton University. Computer Science 217: Introduction to Programming Systems. Process Management

Princeton University Computer Science 217: Introduction to Programming Systems. Process Management

Process Management 1

fork System-Level Function

Process Management! Goals of this Lecture!

Process Management 1

CSC 1600 Unix Processes. Goals of This Lecture

Process Management! Goals of this Lecture!

Processes. Operating System CS 217. Supports virtual machines. Provides services: User Process. User Process. OS Kernel. Hardware

Operating System Structure

Fall 2015 COMP Operating Systems. Lab #3

CSCB09: Software Tools and Systems Programming. Bianca Schroeder IC 460

EECE.4810/EECE.5730: Operating Systems Spring 2017 Homework 1 Solution Due 3:15 PM, Wednesday, 2/1/17

Unix-Linux 2. Unix is supposed to leave room in the process table for a superuser process that could be used to kill errant processes.

UNIX Processes. by Armin R. Mikler. 1: Introduction

Week 2 Intro to the Shell with Fork, Exec, Wait. Sarah Diesburg Operating Systems CS 3430

Processes: Introduction. CS 241 February 13, 2012

CS 201. Processes. Gerson Robboy Portland State University

CPSC 341 OS & Networks. Processes. Dr. Yingwu Zhu

CS 550 Operating Systems Spring Process III

Operating systems and concurrency - B03

UNIX. Session 2. UNIX processes and forking fork system call exec system call death of process kill fork and I/O using it UNIX.

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2018 Lecture 20

Announcement (1) sys.skku.edu is now available

Giving credit where credit is due

Q & A (1) Where were string literals stored? Virtual Address. SSE2033: System Software Experiment 2 Spring 2016 Jin-Soo Kim

Processes. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

CSci 4061 Introduction to Operating Systems. Processes in C/Unix

CSC 252: Computer Organization Spring 2018: Lecture 19

CSCI 4061: Making Processes

Carnegie Mellon. Processes. Lecture 12, May 19 th Alexandre David. Credits to Randy Bryant & Dave O Hallaron from Carnegie Mellon

Lesson 2. process id = 1000 text data i = 5 pid = 1200

OS Interaction and Processes

Parents and Children

518 Lecture Notes Week 3

Windows architecture. user. mode. Env. subsystems. Executive. Device drivers Kernel. kernel. mode HAL. Hardware. Process B. Process C.

CSE 153 Design of Operating Systems Fall 2018

University of Washington What is a process?

CS240: Programming in C

COE518 Lecture Notes Week 2 (Sept. 12, 2011)

Operating Systems. Lecture 05

Processes. Today. Next Time. ! Process concept! Process model! Implementing processes! Multiprocessing once again. ! Scheduling processes

Exceptional Control Flow Part I Oct. 17, 2002

Introduction to Processes

CSC209H Lecture 6. Dan Zingaro. February 11, 2015

Control Flow. Systemprogrammering 2007 Föreläsning 2 Exceptional Control Flow Part I. Exceptional Control Flow. Altering the Control Flow

Exceptional Control Flow Part I

Process. Heechul Yun. Disclaimer: some slides are adopted from the book authors slides with permission 1

Today. Introduction to Computer Systems /18 243, Fall th Lecture. Control Flow. Altering the Control Flow.

Processes. CSE 351 Autumn Instructor: Justin Hsia

CITS2002 Systems Programming. Creating a new process using fork() 1 next CITS2002 CITS2002 schedule

Processes. CSE 351 Autumn Instructor: Justin Hsia

Exceptional Control Flow Part I September 22, 2008

API Interlude: Process Creation (DRAFT)

Process a program in execution; process execution must progress in sequential fashion. Operating Systems

Altering the Control Flow

Are branches/calls the only way we can get the processor to go somewhere in a program? What is a program? A processor? A process?

Final Precept: Ish. Slides Originally Prepared by: Wonho Kim

Process Control. Philipp Koehn. 23 April 2018

Reading Assignment 4. n Chapter 4 Threads, due 2/7. 1/31/13 CSE325 - Processes 1

Lecture Topics. Announcements. Today: Threads (Stallings, chapter , 4.6) Next: Concurrency (Stallings, chapter , 5.

Altering the Control Flow

PROCESS CONTROL BLOCK TWO-STATE MODEL (CONT D)

Today. Exceptional Control Flow Processes. Exceptions and Processes. Control Flow. Altering the Control Flow

Exceptional Control Flow Part I

Processes & Threads. Today. Next Time. ! Process concept! Process model! Implementing processes! Multiprocessing once again. ! More of the same J

Introduction to Operating Systems Prof. Chester Rebeiro Department of Computer Science and Engineering Indian Institute of Technology, Madras

ECE 550D Fundamentals of Computer Systems and Engineering. Fall 2017

Exceptions, Processes and Signals

CS 550 Operating Systems Spring Process II

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

Processes, Exceptional

CSC209 Fall Karen Reid 1

Exceptional Control Flow: Exceptions and Processes

CS 355 Operating Systems. Keeping Track of Processes. When are processes created? Process States 1/26/18. Processes, Unix Processes and System Calls

Processes. CS439: Principles of Computer Systems January 24, 2018

Introduction to OS Processes in Unix, Linux, and Windows MOS 2.1 Mahmoud El-Gayyar

CS3733: Operating Systems

Processes COMPSCI 386

TCSS 422: OPERATING SYSTEMS

What Is A Process? Process States. Process Concept. Process Control Block (PCB) Process State Transition Diagram 9/6/2013. Process Fundamentals

Assignment 1. Teaching Assistant: Michalis Pachilakis (

Processes. q Process concept q Process model and implementation q Multiprocessing once again q Next Time: Scheduling

Processes. CS439: Principles of Computer Systems January 30, 2019

Prepared by Prof. Hui Jiang Process. Prof. Hui Jiang Dept of Electrical Engineering and Computer Science, York University

Process. Prepared by Prof. Hui Jiang Dept. of EECS, York Univ. 1. Process in Memory (I) PROCESS. Process. How OS manages CPU usage? No.

Processes. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Operating Systems Lab

CSCE 313 Introduction to Computer Systems. Instructor: Dezhen Song

Chap 4, 5: Process. Dongkun Shin, SKKU

CSCE 313: Intro to Computer Systems

Exceptional Control Flow Part I Oct. 28, 2009"

Unix Processes 1 / 31

SE350: Operating Systems

Concurrency. Stefan D. Bruda. Winter 2018

Exceptional Control Flow: Exceptions and Processes

Programming Assignment #1: A Simple Shell

Preview. Process Control. What is process? Process identifier The fork() System Call File Sharing Race Condition. COSC350 System Software, Fall

PROCESS MANAGEMENT. Operating Systems 2015 Spring by Euiseong Seo

Lecture 4: Process Management

Transcription:

Princeton University Computer Science 217: Introduction to Programming Systems Process Management 1

Goals of this Lecture Help you learn about: Creating new processes Waiting for processes to terminate Executing new programs Shell structure Why? Creating new processes and executing new programs are fundamental tasks of a Unix shell See Assignment 7 A power programmer knows about Unix shells 2

System-Level Functions As noted in the Exceptions and Processes lecture Linux system-level functions for process management Number Function Description 60 exit() Terminate the process 57 fork() Create a child process 7 wait() Wait for child process termination 11 execvp() Execute a program in current process 20 getpid() Return the process id of the current process 3

Agenda Creating new processes Waiting for processes to terminate Executing new programs Shell structure 4

Why Create New Processes? Why create a new process? Scenario 1: Program wants to run an additional instance of itself E.g., web server receives request; creates additional instance of itself to handle the request; original instance continues listening for requests Scenario 2: Program wants to run a different program E.g., shell receives a command; creates an additional instance of itself; additional instance overwrites itself with requested program to handle command; original instance continues listening for commands How to create a new process? A parent process forks a child process (Optionally) child process overwrite itself with a new program 5

fork System-Level Function pid_t fork(void); Create a new process by duplicating the calling process New (child) process is an exact duplicate of the calling (parent) process In the child, return 0 In the parent, return the process id of the child fork() is called once in parent process fork() returns twice Once in parent process Once in child process 6

Creating New Processes Parent process and child process run concurrently Two CPUs available Parent process and child process run in parallel Fewer than two CPUs available Parent process and child process run serially OS provides the illusion of parallel execution OS causes context switches between the two processes (Recall Exceptions and Processes lecture) Reality: Each CourseLab computer has 24 CPUs Simplifying assumption: there is only one CPU We ll speak of which process gets the CPU 7

Simple fork Example { printf("one\n"); fork(); printf("two\n"); return 0; What is the output? 8

Simple fork Example Trace 1 (1) Parent prints one { printf("one\n"); fork(); printf("two\n"); return 0; 9

Executing concurrently Simple fork Example Trace 1 (2) Parent forks child { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 10

Executing concurrently Simple fork Example Trace 1 (3) OS gives CPU to child; child prints two { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 11

Executing concurrently Simple fork Example Trace 1 (4) Child exits { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 12

Simple fork Example Trace 1 (5) OS gives CPU to parent; parent prints two { printf("one\n"); fork(); printf("two\n"); return 0; 13

Simple fork Example Trace 1 (6) OS gives CPU to parent; parent prints two { printf("one\n"); fork(); printf("two\n"); return 0; 14

Simple fork Example Trace 1 Output Output: one two two From parent From child From parent 15

Simple fork Example Trace 2 (1) Parent prints one { printf("one\n"); fork(); printf("two\n"); return 0; 16

Executing concurrently Simple fork Example Trace 2 (2) Parent forks child { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 17

Executing concurrently Simple fork Example Trace 2 (3) OS gives CPU to parent; parent prints two { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 18

Executing concurrently Simple fork Example Trace 2 (4) Parent exits { printf("one\n"); fork(); printf("two\n"); return 0; { printf("one\n"); fork(); printf("two\n"); return 0; 19

Simple fork Example Trace 2 (5) OS gives CPU to child; child prints two { printf("one\n"); fork(); printf("two\n"); return 0; 20

Simple fork Example Trace 2 (6) Child exits { printf("one\n"); fork(); printf("two\n"); return 0; 21

Simple fork Example Trace 2 Output Output: one two two From parent From parent From child 22

Fact 1: fork and Process State Immediately after fork(), parent and child have identical but distinct process states Contents of registers Contents of memory File descriptor tables (Relevant later) Etc. See Bryant & O Hallaron book for details 23

Fact 2: fork and Process Ids Any process has a unique nonnegative integer id Parent process and child processes have different process ids No process has process id 0 24

Fact 3: fork and Return Values Return value of fork has meaning In child, fork() returns 0 In parent, fork() returns process id of child if (pid == 0) { /* in child */ else { /* in parent */ 25

fork Example #include <sys/types.h> { pid_t pid; int x = 1; if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); What is the output? 26

fork Example Trace 1 (1) #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); 27

Executing concurrently fork Example Trace 1 (2) Parent forks child #include <sys/types.h> { pid_t pid; int x = 1; x = 1 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); 28

Executing concurrently fork Example Trace 1 (3) Assume OS gives CPU to child #include <sys/types.h> { pid_t pid; int x = 1; x = 1 0 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 29

Executing concurrently fork Example Trace 1 (4) Child decrements its x, and prints child: 0 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 #include <sys/types.h> { pid_t pid; int x = 1; x = 0 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 30

Executing concurrently fork Example Trace 1 (5) Child exits; OS gives CPU to parent #include <sys/types.h> { pid_t pid; int x = 1; x = 1 #include <sys/types.h> { pid_t pid; int x = 1; x = 0 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 31

fork Example Trace 1 (6) In parent, fork() returns process id of child #include <sys/types.h> { pid_t pid; int x = 1; x = 1 Process id of child if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 32

fork Example Trace 1 (7) Parent increments its x, and prints parent: 2 #include <sys/types.h> { pid_t pid; int x = 1; x = 2 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 33

fork Example Trace 1 (8) Parent exits #include <sys/types.h> { pid_t pid; int x = 1; x = 2 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 34

fork Example Trace 1 Output Example trace 1 output: Child: 0 Parent: 2 35

fork Example Trace 2 (1) #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); 36

Executing concurrently fork Example Trace 2 (2) Parent forks child #include <sys/types.h> { pid_t pid; int x = 1; x = 1 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); if (pid == 0) { x--; printf("child: %d\n", x); else { x++; printf("parent: %d\n", x); 37

Executing concurrently fork Example Trace 2 (3) Assume OS gives CPU to parent #include <sys/types.h> { pid_t pid; int x = 1; x = 1 Process ID of child #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 38

Executing concurrently fork Example Trace 2 (4) Parent increments its x and prints parent: 2 #include <sys/types.h> { pid_t pid; int x = 1; x = 2 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 39

Executing concurrently fork Example Trace 2 (5) Parent exits; OS gives CPU to child #include <sys/types.h> { pid_t pid; int x = 1; x = 2 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 40

fork Example Trace 2 (6) In child, fork() returns 0 0 #include <sys/types.h> { pid_t pid; int x = 1; x = 1 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 41

fork Example Trace 2 (7) Child decrements its x and prints child: 0 #include <sys/types.h> { pid_t pid; int x = 1; x = 0 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 42

fork Example Trace 2 (8) Child exits #include <sys/types.h> { pid_t pid; int x = 1; x = 0 if (pid == 0) { x--; printf( child: %d\n", x); else { x++; printf( parent: %d\n", x); 43

fork Example Trace 2 Output Example trace 2 output: Parent: 2 Child: 0 44

Agenda Creating new processes Waiting for processes to terminate Executing new programs Shell structure 45

wait System-Level Function Problem: How to control execution order? Solution: Parent should call wait() (child is a zombie until parent does the wait(), so the parent should harvest (or reap) its children... more later) pid_t wait(int *status); Suspends execution of the calling process until one of its children terminates If status is not NULL, stores status information in the int to which it points; this integer can be inspected with macros [see man page for details]. On success, returns the process ID of the terminated child On error, returns -1 Paraphrasing man page 46

wait Example #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; What is the output? 47

Executing concurrently wait Example Trace 1 (1) Parent forks child #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 48

Executing concurrently wait Example Trace 1 (2) OS gives CPU to parent #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 49

Executing concurrently wait Example Trace 1 (3) Parent calls wait() #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 50

Executing concurrently wait Example Trace 1 (4) OS gives CPU to child #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 51

Executing concurrently wait Example Trace 1 (5) Child prints child and exits #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 52

wait Example Trace 1 (6) Parent returns from call of wait(), prints parent, exits #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 53

wait Example Trace 1 Output Example trace 1 output child parent 54

Executing concurrently wait Example Trace 2 (1) Parent forks child #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 55

Executing concurrently wait Example Trace 2 (2) OS gives CPU to child #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 56

Executing concurrently wait Example Trace 2 (3) Child prints child and exits #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 57

wait Example Trace 2 (4) OS gives CPU to parent #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 58

wait Example Trace 2 (5) Parent calls wait(); returns immediately #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 59

wait Example Trace 2 (6) Parent prints parent and exits #include <sys/types.h> #include <wait.h> { pid_t pid; if (pid == 0) { printf("child\n"); wait(null); printf("parent\n"); return 0; 60

wait Example Trace 2 Output Example trace 2 output child parent Same as trace 1 output! 61

Aside: Orphans and Zombies Question: What happens if parent process does not wait for (reap/harvest) child process? Answer 1: In shell, could cause sequencing problems E.g, parent process running shell writes prompt for next command before current command is finished executing Answer 2: In general, child process becomes zombie and/or orphan 62

Aside: Orphans and Zombies Orphan A process that has no parent Zombie A process that has terminated but has not been waited for (reaped) Orphans and zombies Clutter Unix data structures unnecessarily OS maintains unnecessary PCBs Can become long-running processes Consume CPU time unnecessarily polychlorinated biphenyls? no, process control blocks! 63

Aside: Orphans and Zombies Parent waits for child Child exits Normal Child exits Parent exits Terms inside boxes indicate condition of child process OK Zombie Orphan Parent waits for child Parent exits Process 1 adopts child OK Orphan Zombie Process 1 adopts child Zombie Process 1 detects that child has exited, and waits for child Normal Child exits Zombie Child never exits Possible trouble Process 1 detects that child has exited, and waits for child OK OK 64

Agenda Creating new processes Waiting for processes to terminate Executing new programs Shell structure 65

execvp System-Level Function Problem: How to execute a new program? Usually, in the newly-created child process Solution: execvp() int execvp(const char *file, char *const argv[]); Replaces the current process image with a new process image Provides an array of pointers to null-terminated strings that represent the argument list available to the new program The first argument, by convention, should point to the filename associated with the file being executed The array of pointers must be terminated by a NULL pointer Paraphrasing man page 66

execvp System-Level Function Example: Execute cat readme char *newcmd; char *newargv[3]; newcmd = "cat"; newargv[0] = "cat"; newargv[1] = "readme"; newargv[2] = NULL; execvp(newcmd, newargv); First argument: name of program to be executed Second argument: argv to be passed to main() of new program Must begin with program name, end with NULL 67

execvp Failure fork() If successful, returns two times Once in parent Once in child char *newcmd; char *newargv[3]; newcmd = "cat"; newargv[0] = "cat"; newargv[1] = "readme"; newargv[2] = NULL; execvp(newcmd, newargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); execvp() If successful, returns zero times Calling program is overwritten with new program Corollary: If execvp() returns, then it must have failed 68

execvp Example $ cat readme This is my readme file. 69

execvp Example What is the { char *newcmd; output? char *newargv[3]; newcmd = "cat"; newargv[0] = "cat"; newargv[1] = "readme"; newargv[2] = NULL; execvp(newcmd, newargv); fprintf(stderr, "exec failed\n"); return EXIT_FAILURE; 70

execvp Example Trace (1) Process creates arguments to be passed to execvp() { char *newcmd; char *newargv[3]; newcmd = "cat"; newargv[0] = "cat"; newargv[1] = "readme"; newargv[2] = NULL; execvp(newcmd, newargv); fprintf(stderr, "exec failed\n"); return EXIT_FAILURE; 71

execvp Example Trace (2) Process executes execvp() { char *newcmd; char *newargv[3]; newcmd = "cat"; newargv[0] = "cat"; newargv[1] = "readme"; newargv[2] = NULL; execvp(newcmd, newargv); fprintf(stderr, "exec failed\n"); return EXIT_FAILURE; 72

execvp Example Trace (3) cat program executes in same process cat program with argv array: argv[0] = "cat" argv[1] = "readme" argv[2] = NULL 73

execvp Example Trace (4) cat program writes This is my\nreadme file. cat program with argv array: argv[0] = "cat" argv[1] = "readme" argv[2] = NULL 74

execvp Example Trace (5) cat program terminates cat program with argv array: argv[0] = "cat" argv[1] = "readme" argv[2] = NULL 75

execvp Example Trace (6) Output This is my readme file. 76

Agenda Creating new processes Waiting for processes to terminate Executing new programs Shell structure 77

Shell Structure Parent (shell) reads & parses the command line E.g., cat readme Parent forks child Parent waits Child calls execvp to execute command Child exits Parent returns from wait Parent repeats shell fork parent child wait execvp cat readme 78

Simple Shell Code Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous 79

Simple Shell Trace (1) Parent Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous Parent reads and parses command line Parent assigns values to somepgm and someargv 80

executing concurrently Simple Shell Trace (2) Parent Process Child Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous Parse command line Assign values to somefile, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous fork() creates child process Which process gets the CPU first? Let s assume the parent 81

executing concurrently Simple Shell Trace (3) Parent Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous child s pid Child Process Parse command line Assign values to somefile, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous In parent, pid!= 0; parent waits; OS gives CPU to child 82

executing concurrently Simple Shell Trace (4) Parent Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous 0 Child Process Parse command line Assign values to somefile, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous In child, pid == 0; child calls execvp() 83

executing concurrently Simple Shell Trace (5) Parent Process Child Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous somepgm With someargv as argv param In child, somepgm overwrites shell program; main() is called with someargv as argv parameter 84

executing concurrently Simple Shell Trace (6) Parent Process Child Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous somepgm With someargv as argv param Somepgm executes in child, and eventually exits 85

Simple Shell Trace (7) Parent Process Parse command line Assign values to somepgm, someargv if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(exit_failure); /* in parent */ wait(null); Repeat the previous Parent returns from wait() and repeats 86

Background processes Unix shell lets you run a process in the background $ compute <my-input >my-output & How it s implemented in the shell: Don t wait() after the fork! But: must clean up zombie processes waitpid(0, &status, WNOHANG) (more info: man 2 wait ) When to do it? Every time around the main loop, or When parent receives the SIGCHLD signal. One or the other, don t need both!

Aside: system Function Common combination of operations fork() to create a new child process execvp() to execute new program in child process wait() in the parent process for the child to complete Single call that combines all three int system(const char *cmd); Example { system("cat readme"); return 0; 88

Aside: system Function Question: Why not use system() instead of fork()/execvp()/wait() in Assignment 7 shell? Shallow answer: Assignment requirements! Deeper answer: Using system(), shell could not handle signals as specified See Signals reference notes 89

Aside: fork Efficiency Question: fork() duplicates an entire process (text, bss, data, rodata, stack, heap sections) Isn t that very inefficient???!!! Answer: Using virtual memory, not really! Upon fork(), OS creates virtual pages for child process Each child virtual page maps to physical page (in memory or on disk) of parent OS duplicates physical pages incrementally, and only if/when write occurs ( copy-on-write ) 90

Aside: exec Efficiency Question: execvp() loads a new program from disk into memory Isn t that somewhat inefficient? Answer: Using virtual memory, not really! Upon execvp(), OS changes process s virtual page table to point to pages on disk containing the new program As page faults occur, OS swaps pages of new program into memory incrementally as needed 91

Aside: fork/exec Efficiency The bottom line fork() and execvp() are efficient Because they were designed with virtual memory in mind! Commentary: A beautiful intersection of three beautiful abstractions 92

Assignment 7 Suggestion A shell is mostly a big loop Read char array from stdin Lexically analyze char array to create token array Parse token array to create command Execute command Fork child process Parent: Wait for child to terminate Child: Exec new program Start with code from earlier slides and from precepts And edit until it becomes a Unix shell! 93

Summary Creating new processes fork() Executing new programs execvp() Waiting for processes to terminate wait() Shell structure Combination of fork(), execvp(), wait() 94