Core Concepts of Processes
A program is a static collection of instructions stored on disk. A process is the dynamic execution instance of a program, encompassing lifecycle phases such as creation, scheduling, and termination.
Key System Commands
-
top: Displays real-time system processes sorted by CPU usage. Key fields include:
- PID: Unique process identifier (positive integer).
- Priority (NI): Lower values indicate higher priority (-20 to +19).
- State codes:
- R: Running or ready.
- S: Interruptible sleep.
- D: Uninterruptible sleep.
- T: Stopped.
- Z: Zombie (terminated but not reaped).
- X: Dead.
- Press
qto exit.
-
nice: Launches a process with a specified priority.
nice -n 5 ./program -
renice: Adjusts priority of an already running process.
renice -n 10 1234 -
kill: Terminates a process by PID.
kill -9 1234 -
killall: Kills all processes matching a name.
killall -9 httpd -
ps -ef: Lists all curent processes with parent-child relationships (PPID shows parent PID).
ps -ef | grep a.out -
pstree: Visualizes process hierarchy as a tree structure.
-
ps -aux: Shows detailed process info including terminal association (TTY).
-
./a.out &: Runs a program in background. Use
fgfollowed by job number to bring it back to foreground. -
jobs: Lists active background jobs in the current shell session.
Memory Layout and Virtual Address Space
On 32-bit systems, each process has a 4GB virtual address space divided into:
-
Text Segment: Holds executable code and instructions.
-
Data Segment:
- Read-only strings.
- Initialized global/static variables.
- Uninitialized global/static variables (zero-initialized).
-
Stack Area:
- Grows downward from high memory.
- Stores local variables; space allocated at definition, freed when scope ends.
- Default size ~8MB.
-
Heap Area:
- Grows upward from low memory.
- Manually managed via
malloc()andfree().
The MMU (Memory Management Unit) maps virtual addresses to physical ones dynamically during execution.
Process Scheduling Mechanisms
Common algorithms:
- First-Come, First-Served (FCFS)
- Priority-based Scheduling
- Round Robin (time quantum per task)
- Multilevel Feedback Queue
- Load Balancing
Core principle: Macroscopic sequentiality, microscopic parallelism.
Process states:
- R: Running or ready.
- S: Sleeping (wakeup interruptible).
- D: Sleeping (uninterruptible).
- T: Stopped.
- Z: Zombie (exit completed, resources unreclaimed).
- X: Terminated (resources fully released).
Essential Process APIs
fork()
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
Creates a child process. Returns:
- 0 in child.
- Child's PID in parent.
- -1 on failure.
Child inherits parent’s text, data, and stack segments.
getpid()
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
Returns the calling process ID.
getppid()
pid_t getppid(void);
Returns the parent process ID.
Example usage:
#include "head.h"
int main(void)
{
pid_t child_pid = fork();
if (child_pid == 0)
{
printf("Child: PID=%d, PPID=%d\n", getpid(), getppid());
}
else if (child_pid > 0)
{
printf("Parent: PID=%d, Child_PID=%d\n", getpid(), child_pid);
}
printf("Hello World!\n");
while (1) { /* Keep alive */ }
return 0;
}
exit() vs _exit()
-
exit(int status):
- Performs cleanup (flushes buffers), then terminates.
- Equivalent to
returninmain().
-
_exit(int status):
- Immediate termination without buffer flush.
// exit() example
printf("Hello world!");
exit(0);
printf("This won't print\n");
// _exit() example
printf("Hello world!");
_exit(0);
printf("This also won't print\n");
Process Termination and Reaping
Zombie Process
Occurs when a child exits but its parent hasn’t called wait(). The process remains in the process table until reaped.
Prevention:
- Have parent call
wait()afterfork(). - Allow parent to terminate first (orphaned child adopted by init).
Orphan Process
When parent dies before child. The child is adopted by the system init process (PID 1), which ensures resource cleanup.
wait()
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
Waits for any child process to terminate. Blocks until a child exits.
wstatus: Optional pointer to store exit status.- Returns child PID on success, -1 on error.
Practical Example: Multiple Child Processes
Create nine child processes, each printing its own PID and parent PID. Parent prints its PID and all child PIDs.
#include "head.h"
int main(void)
{
pid_t children[9] = {0};
int i;
for (i = 0; i < 9; ++i)
{
children[i] = fork();
if (children[i] == -1)
{
perror("Failed to fork");
return -1;
}
if (children[i] == 0)
{
printf("Child[%d]: PID=%d, Parent=%d\n", i+1, getpid(), getppid());
break;
}
}
sleep(1);
if (children[i] > 0)
{
printf("Parent: PID=%d\n", getpid());
for (i = 0; i < 9; ++i)
{
printf("Child[%d]: PID=%d\n", i+1, children[i]);
}
}
while (1) { sleep(5); break; }
return 0;
}