Threads
Thread
In early operating systems, processes were the basic units of resource ownership and independent execution. As computer technology developed, their drawbacks became apparent: creating, removing, and switching resource-owning processes involved significant time and space overhead. Threads were subsequently introduced as independently executable units.
A thread is a basic unit of OS scheduling, belongs to a process, and carries out its execution. A process can contain several concurrent threads, which can execute different tasks in parallel when hardware and runtime conditions permit.
Shared data, private execution state
Unlock the complete interactive lab, deeper explanations, and curated reference answers.
Because threads normally share process resources, creating, ending, and switching them often costs less than doing so for separate processes. This can improve concurrency, resource utilization, and throughput. Threads therefore offer several benefits:
- Creating a thread usually takes less time than creating a process.
- Ending a thread usually takes less time than ending a process.
- Switching between threads within one process usually takes less time.
- Threads belong to a process and share its resources, while retaining their own stacks and execution state.
KNOWLEDGE QUIZ
Child Processes
fork() is a function on UNIX and UNIX-like systems that creates a child with initial contents similar to the parent's. Parent and child continue separately after fork() returns, like two users starting copies of the same application.
Creating a Child Process
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
fflush(NULL);
pid_t child = fork();
if (child < 0) {
perror("fork");
return 1;
}
if (child == 0) {
execlp("/bin/ls", "ls", (char *)NULL);
_exit(127);
}
int status;
if (waitpid(child, &status, 0) < 0) {
perror("waitpid");
return 1;
}
return 0;
}Step through fork and exec
Unlock the complete interactive lab, deeper explanations, and curated reference answers.
Normally, a parent creates a child, which can create further processes. Parent and child execute asynchronously, so the parent cannot predict the child's completion merely from its own progress. The parent can call wait() or waitpid() to wait for completion, obtain the exit status, and reap the remaining process record.
Some situations produce zombie and orphan processes:
- Zombie: the child has exited, but the parent has not collected its status with wait() or waitpid(), leaving its process record in the system.
- Orphan: the parent has exited while one or more children are still running. They are adopted by init or another designated process, which collects their status after they exit.
C programming: one fork, two values
Write fork_values.c on Linux, macOS, or another POSIX system. Start with int value = 10 and call fork once.
- In the child, add 5 to value, print it, and exit with status 3.
- In the parent, use waitpid to wait for this child, then print the parent's value and the child's exit status.
- Handle fork/waitpid errors and predict the three output lines before running the program.