Ch 8 Process Control
Although process IDs are unique, they are reusable.
Most systems implement a delayed reuse algorithm that assigns IDs to new processes different from the IDs recently used by terminated processes, preventing new processes from being mistaken for previous ones.
The process with ID=0 is the scheduler process, commonly known as the swapper process.
The process with ID=1 is the init process, responsible for starting a UNIX system after kernel bootstrapping. It runs as a regular user process with superuser privileges and serves as the parent of all orphaned processes.
There are also other kernel processes providing operating system services.
fork
The fork call executes once but returns twice: the child process returns 0 (since it can call getpid to obtain the parent’s ID), while the parent process returns the ID of the newly created process (because there’s no interface to obtain all child process IDs).
Typically, parent and child share the text segment, while other segments depend on the situation. If copy-on-write is employed, segments remain shared until modification occurs.
The execution order of parent and child processes depends on the kernel’s scheduling algorithm.
Difference between sizeof and strlen:
- strlen does not count the null byte in its length
- sizeof includes the null byte in its length
If buffered I/O is called before fork, the buffer is also copied during fork. Since all open file descriptors are duplicated to the child process, if we redirect the parent’s standard output, the child’s standard output will be redirected in the same way. Since offsets are also shared, content will be appended rather than overwritten.
Process synchronization is needed when reading/writing shared file descriptors, or one party (such as the parent process) should actively close unnecessary file descriptors or wait for the other party to complete first.
fork Failure?
- Too many processes
- Total number of processes for the user ID exceeds system limit CHILD_MAX
Usage
- Want to self-replicate and execute different code segments - network services
- One process needs to execute different programs - shell
vfork guarantees that the child process runs first, and only after it calls exec or exit will the parent process be scheduled for execution. Until then, the parent process remains suspended.
exit
The kernel stores exit status, which parent processes retrieve using wait or waitpid. If the parent process terminates before the child, the child automatically becomes a child of the init process (ID 1). Before termination, the kernel checks whether the process’s parent is also terminating.
wait/waitpid
- If all child processes are still running, block
- If a child process has terminated, obtain termination status and return immediately
- If no child processes exist, return error immediately
wait blocks and waits, while waitpid does not block.
If a process forks a child but doesn’t want to wait for child termination nor leave it as a zombie, it can choose to fork twice, allowing the first child process to exit, so the grandchild process gets adopted by init.
exec
Simply replaces the current process’s text segment, data segment, heap segment, and stack segment with a new program from disk.
Process Accounting
After each process terminates, the kernel writes an accounting record containing command name, total CPU time, user ID and group ID, start time, etc. This data can be found in the process table.
Accounting records are written only after termination, so if a process doesn’t terminate, we cannot obtain its accounting record. Records in the accounting file are ordered according to termination sequence.
Accounting records correspond to processes rather than programs. A newly forked process initializes a record; if a process executes multiple programs, the command name in the record becomes the last executed program, and CPU time is the sum of all executed programs.
Process Scheduling
See kernel notes