Process API Study Notes
INTERLUDE: PROCESS API
Introduction to Interludes
Interludes cover practical aspects of systems, focusing on operating system APIs and their usage.
Working with practical skills is emphasized, as these are often valued in the job market.
Overview of Process Creation in UNIX Systems
Discusses process creation using the fork() and exec() system calls in UNIX systems.
Introduces the wait() system call for processes wishing to wait for the completion of child processes.
Central question: How to create and control processes and design interfaces that are user-friendly and useful.
5.1 The fork() System Call
Definition: The fork() system call is utilized to create a new process.
Forking is described as a strange routine that creates an almost exact copy of the calling process.
Execution Example:
A typical structure of a program invoking fork:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> main(int argc, char *argv[]) { printf("hello world (pid: %d)\n", (int) getpid()); int rc = fork(); if (rc < 0) { fprintf(stderr, "fork failed\n"); exit(1); } else if (rc == 0) { // child (new process) } else { printf("hello, I am child (pid: %d)\n", (int) getpid()); printf("hello, I am parent of %d (pid: %d)\n", rc, (int) getpid()); } return 0; }The program prints its PID (Process Identifier). Initial message shows the parent process.
After calling fork(), both the parent and child processes execute, but the child will return a value of 0 while the parent will receive the PID of the child (rc).
5.2 Understanding Fork Output Non-Determinism
Output example and its variability:
Output order is non-deterministic; either child or parent may print first based on CPU scheduling:
Example Output 1:
prompt/pl hello world (pid: 29146) hello, I am parent of 29147 (pid: 29146) hello, I am child (pid: 29147) prompt>Example Output 2:
prompt> hello world (pid: 29146) hello, I am child (pid: 29147) hello, I am parent of 29147 (pid: 29146) prompt>
The CPU scheduler determines which process runs at any moment, leading to potential scenarios in the order of execution.
Adding wait() System Call
Purpose of wait(): To allow the parent process to wait for the completion of a child process.
Modified Output Determinism: After adding wait(), the parent's output can be made deterministic.
Example Program with wait():
int wc = wait(NULL);
printf("hello, I am parent of %d (wc: %d) (pid: %d)\n", rc, wc, (int) getpid());
The parent will always complete its execution after the child completes, ensuring consistent output.
5.3 The exec() System Call
Definition: The exec() system call is utilized to run a different program than the one currently executing.
Execution Example: Running
wcUsing execvp():Here’s how it transforms process execution:
// child: execute different program
char *myargs[3];
myargs[0] = strdup("wc");
myargs[1] = strdup("p3.c"); // argument: file to count
myargs[2] = NULL; // marks end of array
execvp(myargs[0], myargs);
After calling exec(), the previous program execution is replaced, meaning if exec() is successful, it does not return control back to the previous program.
5.4 Motivating the API
Rationale for Separation of fork() and exec(): Permits additional actions to be performed after the fork before the exec call, allowing for modifications to child process environment.
Example: A shell uses fork() and exec() to run commands.
Output Redirection Example: Redirecting output to a file using:
prompt wc p3.c > newfile.txt
Process: The shell closes STDOUT, opens a file, and any output from the
wcprogram is directed to the file.
5.5 Other Parts of the API
Other important system calls include:
kill(): Sends signals to processes for management such as sleep or termination.
Process observation tools like
psandtopto monitor active processes and resource usage.
5.6 Summary
The primary APIs for UNIX process creation include fork(), exec(), and wait().
A deeper understanding of these calls and related concepts can be found in resources like W. Richard Stevens's books.