2 - Process
Process
Section titled “Process”Process : Memory Layout
Section titled “Process : Memory Layout”/* This file is part of the sample code and exercises * used by the class "Advanced Programming in the UNIX * Environment" taught by Jan Schaumann * <jschauma@netmeister.org> at Stevens Institute of * Technology. * * This file is in the public domain. * * You don't have to, but if you feel like * acknowledging where you got this code, you may * reference me by name, email address, or point * people to the course website: * https://stevens.netmeister.org/631/ */
/* This program allows us to visualize the layout of a * process in memory, printing the addresses of * various parts of the program, including components * in the text, data, and bss segments as well as on * the heap and the stack. * * This program can also illustrate a stack overflow * if compiled with '-DSTACKOVERFLOW'. */
#include <err.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>
#define ARRAY_SIZE 16#define MALLOC_SIZE 32
char array[ARRAY_SIZE];char *string = "a string";char *string2;int num = 10;int num2;
extern char **environ;
void func(int);void func2(const char *);
intmain(int argc, char **argv) { int var; char *ptr;
char func_array[ARRAY_SIZE];
(void)printf("High address (args and env):\n"); (void)printf("----------------------------\n"); (void)printf("environ[0] at : 0x%12lX\n", (unsigned long)environ); (void)printf("last arg at : 0x%12lX\n", (unsigned long)&argv[argc]); (void)printf("first arg at : 0x%12lX\n", (unsigned long)&argv[0]); (void)printf("\n");
(void)printf("Stack:\n"); (void)printf("------\n"); (void)printf("First variable inside main at : 0x%12lX\n", (unsigned long)&var); (void)printf("func_array[] ends at : 0x%12lX\n", (unsigned long)&func_array[ARRAY_SIZE]); (void)printf("func_array[] (like 'array[]', but on stack) begins at : 0x%12lX\n", (unsigned long)&func_array[0]);
(void)printf("argc at : 0x%12lX\n", (unsigned long)&argc); (void)printf("argv at : 0x%12lX\n", (unsigned long)&argv);
func2("from main"); func(0);
(void)printf("\n");
(void)printf("Heap:\n"); (void)printf("-----\n"); if ((ptr = malloc(MALLOC_SIZE)) == NULL) { err(EXIT_FAILURE, "unable to allocate memory"); /* NOTREACHED */ }
(void)printf("malloced area ends at : 0x%12lX\n", (unsigned long)ptr+MALLOC_SIZE); (void)printf("malloced area begins at : 0x%12lX\n", (unsigned long)ptr); free(ptr); (void)printf("\n");
(void)printf("Uninitialized Data (BSS):\n"); (void)printf("-------------------------\n"); (void)printf("array[] ends at : 0x%12lX\n", (unsigned long)&array[ARRAY_SIZE]); (void)printf("array[] (uninitialized, fixed-size char * on BSS) from : 0x%12lX\n", (unsigned long)&array[0]); (void)printf("num2 (uninitialized global int) at : 0x%12lX\n", (unsigned long)&num2); (void)printf("string2 (uninitialized global char *) at : 0x%12lX\n", (unsigned long)&string2); (void)printf("extern **environ at : 0x%12lX\n", (unsigned long)&environ); (void)printf("\n");
(void)printf("Initialized Data:\n"); (void)printf("-----------------\n"); (void)printf("num (initialized global int) at : 0x%12lX\n", (unsigned long)&num); (void)printf("string (initialized global char *) at : 0x%12lX\n", (unsigned long)&string); (void)printf("\n");
(void)printf("Text Segment:\n"); (void)printf("-------------\n"); (void)printf("func2 (function) at : 0x%12lX\n", (unsigned long)&func2); (void)printf("func (function) at : 0x%12lX\n", (unsigned long)&func); (void)printf("main (function) at : 0x%12lX\n", (unsigned long)&main); (void)printf("\n");
return EXIT_SUCCESS;}
voidfunc(int recurse) { int fint; char *msg = "from func";
/* Change this value to 0 and note how * the location of where it is stored * changes from the Data to BSS segment. */ static int n = 1; (void)printf("func frame at : 0x%12lX\n", (unsigned long)&fint);
if (recurse) { msg = "recursive"; } (void)printf("static int n within func at : 0x%12lX\n", (unsigned long)&n); printf("func (called %5d times): frame at : 0x%12lX\n", n, (unsigned long)&fint);
n++; func2(msg);}
voidfunc2(const char *how) { int fint; (void)printf("func2 (%s): frame at : 0x%12lX\n", how, (unsigned long)&fint);#ifdef STACKOVERFLOW func(1);#endif}OUTPUT
c@c:~/cos3105$ ./memory_layout2High address (args and env):----------------------------environ[0] at : 0x7FFDCBCB41F8last arg at : 0x7FFDCBCB41F0first arg at : 0x7FFDCBCB41E8
Stack:------First variable inside main at : 0x7FFDCBCB4094func_array[] ends at : 0x7FFDCBCB40B0func_array[] (like 'array[]', but on stack) begins at : 0x7FFDCBCB40A0argc at : 0x7FFDCBCB408Cargv at : 0x7FFDCBCB4080func2 (from main): frame at : 0x7FFDCBCB4064func frame at : 0x7FFDCBCB405Cstatic int n within func at : 0x5731C2CFA014func (called 1 times): frame at : 0x7FFDCBCB405Cfunc2 (from func): frame at : 0x7FFDCBCB4024
Heap:-----malloced area ends at : 0x5731C5DE96D0malloced area begins at : 0x5731C5DE96B0
Uninitialized Data (BSS):-------------------------array[] ends at : 0x5731C2CFA040array[] (uninitialized, fixed-size char * on BSS) from : 0x5731C2CFA030num2 (uninitialized global int) at : 0x5731C2CFA048string2 (uninitialized global char *) at : 0x5731C2CFA040extern **environ at : 0x5731C2CFA020
Initialized Data:-----------------num (initialized global int) at : 0x5731C2CFA010string (initialized global char *) at : 0x5731C2CFA018
Text Segment:-------------func2 (function) at : 0x5731C2CF76A0func (function) at : 0x5731C2CF75DBmain (function) at : 0x5731C2CF7209Process : Stack frame
Section titled “Process : Stack frame”- Create file
memory_layout.cmemory_layout.c #include <stdio.h>int global_a;int global_b;void function1(){global_a = 2;global_b = 3;int local_a = 4;int local_b = 5;}int main(){function1();return 0;} - Compile file
gcc -g -o memory_layout memory_layout.c - Debug file
gdb ./memory_layoutTerminal window GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-gitCopyright (C) 2024 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Type "show copying" and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<https://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...--Type <RET> for more, q to quit, c to continue without paging--cReading symbols from ./memory_layout...(gdb) break function1Breakpoint 1 at 0x1131: file memory_layout.c, line 5.(gdb) runStarting program: /home/c/cos3105/memory_layoutThis GDB supports auto-downloading debuginfo from the following URLs:<https://debuginfod.ubuntu.com>Enable debuginfod for this session? (y or [n]) yDebuginfod has been enabled.To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.[Thread debugging using libthread_db enabled]Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".Breakpoint 1, function1 () at memory_layout.c:55 global_a = 2;# Step through to see variables appear(gdb) next # global_a = 2(gdb) next # global_b = 3(gdb) next # int local_a = 4(gdb) next # int local_b = 5# Now see all variables in current frame(gdb) info localslocal_a = 4local_b = 5# Print individual variables(gdb) print local_a$1 = 4(gdb) print local_b$2 = 5# See the stack frames(gdb) bt#0 function1 () at program.c:8#1 0x... in main () at program.c:11# Check what's in the main frame(gdb) frame 1(gdb) info locals# (no local variables in main)# Go back to function1 frame(gdb) frame 0(gdb) info localslocal_a = 4local_b = 5(gdb) exitA debugging session is active.Inferior 1 [process 22869] will be killed.Quit anyway? (y or n) y
Process : Process Control Block (PCB)
Section titled “Process : Process Control Block (PCB)”#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>
// Simplified PCB structure (what OS actually maintains)struct PCB { // PROCESS IDENTIFICATION pid_t process_id; // Unique process ID pid_t parent_id; // Parent process ID char process_name[256]; // Program name
// PROCESS STATE enum process_state { NEW, READY, RUNNING, WAITING, TERMINATED } state;
// CPU REGISTERS (saved during context switch) struct cpu_registers { unsigned long pc; // Program Counter unsigned long sp; // Stack Pointer unsigned long registers[16]; // General purpose registers unsigned long flags; // Status flags } cpu_context;
// MEMORY MANAGEMENT struct memory_info { void* code_segment; // Where program code is loaded void* data_segment; // Where global variables are void* heap_start; // Dynamic memory start void* stack_start; // Stack memory start size_t memory_size; // Total memory used } memory;
// SCHEDULING INFORMATION int priority; // Process priority int cpu_time_used; // How much CPU time consumed int time_slice_remaining; // Time left in current slice
// I/O AND FILES struct file_descriptor_table { int stdin_fd; // Standard input int stdout_fd; // Standard output int stderr_fd; // Standard error int open_files[64]; // Other open files } files;
// PROCESS RELATIONSHIPS struct PCB* parent; // Pointer to parent PCB struct PCB* children[32]; // Pointers to children PCBs int num_children;
// SYNCHRONIZATION int waiting_for_resource; // What resource process waits for struct PCB* next_in_queue; // For ready queue, wait queue, etc.};
// Function to display PCB informationvoid display_pcb_info(struct PCB* pcb) { printf("=== PROCESS CONTROL BLOCK INFO ===\n\n");
printf("IDENTIFICATION:\n"); printf(" Process ID (PID): %d\n", pcb->process_id); printf(" Parent ID (PPID): %d\n", pcb->parent_id); printf(" Process Name: %s\n", pcb->process_name);
printf("\nSTATE:\n"); char* state_names[] = {"NEW", "READY", "RUNNING", "WAITING", "TERMINATED"}; printf(" Current State: %s\n", state_names[pcb->state]);
printf("\nCPU CONTEXT:\n"); printf(" Program Counter: 0x%lx\n", pcb->cpu_context.pc); printf(" Stack Pointer: 0x%lx\n", pcb->cpu_context.sp); printf(" Registers: [saved during context switch]\n");
printf("\nMEMORY:\n"); printf(" Code Segment: %p\n", pcb->memory.code_segment); printf(" Data Segment: %p\n", pcb->memory.data_segment); printf(" Heap Start: %p\n", pcb->memory.heap_start); printf(" Stack Start: %p\n", pcb->memory.stack_start); printf(" Memory Size: %zu bytes\n", pcb->memory.memory_size);
printf("\nSCHEDULING:\n"); printf(" Priority: %d\n", pcb->priority); printf(" CPU Time Used: %d ms\n", pcb->cpu_time_used); printf(" Time Slice Remaining: %d ms\n", pcb->time_slice_remaining);
printf("\nFILES:\n"); printf(" stdin: %d, stdout: %d, stderr: %d\n", pcb->files.stdin_fd, pcb->files.stdout_fd, pcb->files.stderr_fd);
printf("\nRELATIONSHIPS:\n"); printf(" Number of Children: %d\n", pcb->num_children);}
// Simulate creating a PCB for current processstruct PCB* create_current_process_pcb() { struct PCB* pcb = malloc(sizeof(struct PCB));
// Fill in real information about current process pcb->process_id = getpid(); pcb->parent_id = getppid(); snprintf(pcb->process_name, sizeof(pcb->process_name), "demo_process");
pcb->state = RUNNING; // Currently running since we're executing
// Simulate some values (real OS gets these from hardware) pcb->cpu_context.pc = 0x400000; // Typical code start address pcb->cpu_context.sp = 0x7fff0000; // Typical stack address
pcb->memory.code_segment = (void*)0x400000; pcb->memory.data_segment = (void*)0x600000; pcb->memory.heap_start = (void*)0x800000; pcb->memory.stack_start = (void*)0x7fff0000; pcb->memory.memory_size = 1024 * 1024; // 1MB
pcb->priority = 20; // Normal priority pcb->cpu_time_used = 150; pcb->time_slice_remaining = 50;
pcb->files.stdin_fd = 0; pcb->files.stdout_fd = 1; pcb->files.stderr_fd = 2;
pcb->num_children = 0; pcb->waiting_for_resource = 0;
return pcb;}
// Show how PCB is used during context switchingvoid demonstrate_context_switch() { printf("\n=== HOW PCB IS USED IN CONTEXT SWITCHING ===\n\n");
printf("When OS switches from Process A to Process B:\n\n");
printf("1. SAVE Process A's context:\n"); printf(" - Save CPU registers to PCB_A\n"); printf(" - Save program counter to PCB_A\n"); printf(" - Save stack pointer to PCB_A\n"); printf(" - Update PCB_A state to READY\n"); printf(" - Add PCB_A to ready queue\n\n");
printf("2. LOAD Process B's context:\n"); printf(" - Load CPU registers from PCB_B\n"); printf(" - Load program counter from PCB_B\n"); printf(" - Load stack pointer from PCB_B\n"); printf(" - Update PCB_B state to RUNNING\n"); printf(" - Continue execution where B left off\n\n");
printf("The PCB is what makes this possible!\n"); printf("Without PCB, the OS wouldn't know where to resume each process.\n");}
// Show process states using PCBvoid demonstrate_process_states() { printf("\n=== PROCESS STATES IN PCB ===\n\n");
printf("NEW: Process created, PCB allocated, not yet loaded\n"); printf("READY: Process loaded, waiting for CPU assignment\n"); printf("RUNNING: Process currently executing on CPU\n"); printf("WAITING: Process blocked, waiting for I/O or resource\n"); printf("TERMINATED: Process finished, PCB being cleaned up\n\n");
printf("State transitions:\n"); printf("NEW → READY: OS loads process into memory\n"); printf("READY → RUNNING: Scheduler assigns CPU\n"); printf("RUNNING → READY: Time slice expires\n"); printf("RUNNING → WAITING: Process requests I/O\n"); printf("WAITING → READY: I/O completes\n"); printf("RUNNING → TERMINATED: Process exits\n");}
int main() { printf("=== PROCESS CONTROL BLOCK (PCB) DEMONSTRATION ===\n\n");
printf("WHAT IS PCB?\n"); printf("• PCB = Process Control Block\n"); printf("• OS data structure that REPRESENTS a process\n"); printf("• Contains ALL information needed to manage the process\n"); printf("• One PCB per process in the system\n\n");
// Create and display a sample PCB struct PCB* current_pcb = create_current_process_pcb(); display_pcb_info(current_pcb);
demonstrate_context_switch(); demonstrate_process_states();
printf("\n=== KEY POINTS ABOUT PCB ===\n"); printf("✓ PCB REPRESENTS the process to the OS\n"); printf("✓ Process = running program, PCB = OS's record of it\n"); printf("✓ OS uses PCB for scheduling, memory management, I/O\n"); printf("✓ Context switching = saving/loading PCB information\n"); printf("✓ Each process has exactly one PCB\n"); printf("✓ PCB exists even when process is not running\n");
free(current_pcb); return 0;}Process : Create Process
Section titled “Process : Create Process”#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main(){ pid_t p; p=fork(); if(p==0) //child { printf("I am child having PID %d\n",getpid()); printf("My parent PID is %d\n",getppid()); } else //parent { printf("I am parent having PID %d\n",getpid()); printf("My child PID is %d\n",p); } char read[2]; fgets(read,sizeof(read),stdin);}#include <iostream>#include <unistd.h>#include <sys/wait.h>
using namespace std;
int main(){ pid_t pid = fork(); if (pid==0){ cout << "Child ID : " << getpid() << ", Parent ID : " << getppid() << endl; }else{ cout << "Parent ID : " << getpid() << ", Child ID : " << pid << endl;
wait(nullptr); }}OUTPUT
c@c:~/cos3105$ ./create_processI am parent having PID 30752My child PID is 30753I am child having PID 30753My parent PID is 30752- Open another terminal
ps aux | grep "create_process"OUTPUT
c@c:~/cos3105$ ps aux | grep "create_process"c 30752 0.0 0.0 2680 1536 pts/1 S+ 15:06 0:00 ./create_processc 30753 0.0 0.0 2680 896 pts/1 S+ 15:06 0:00 ./create_processc 30837 0.0 0.0 6676 2304 pts/0 S+ 15:06 0:00 grep --color=auto create_processProcess : Show process tree
Section titled “Process : Show process tree”- pstree
pstreeOUTPUT
c@c:~/cos3105$ pstreesystemd─┬─ModemManager───3*[{ModemManager}] ├─agetty ├─cron ├─dbus-daemon ├─multipathd───6*[{multipathd}] ├─node─┬─node─┬─node─┬─bash───pstree │ │ │ ├─bash───create_process───create_process │ │ │ └─12*[{node}] │ │ ├─2*[node───12*[{node}]] │ │ └─10*[{node}] │ └─10*[{node}] ├─polkitd───3*[{polkitd}] ├─rsyslogd───3*[{rsyslogd}] ├─systemd-journal ├─systemd-logind ├─systemd-network ├─systemd-resolve ├─systemd-timesyn───{systemd-timesyn} ├─systemd-udevd ├─udisksd───5*[{udisksd}] ├─unattended-upgr───{unattended-upgr} └─upowerd───3*[{upowerd}]- pstree with PIDs:
pstree -pOUTPUT
c@c:~/cos3105$ pstree -psystemd(1)─┬─ModemManager(816)─┬─{ModemManager}(833) │ ├─{ModemManager}(838) │ └─{ModemManager}(841) ├─agetty(882) ├─cron(873) ├─dbus-daemon(729) ├─multipathd(365)─┬─{multipathd}(381) │ ├─{multipathd}(382) │ ├─{multipathd}(383) │ ├─{multipathd}(384) │ ├─{multipathd}(385) │ └─{multipathd}(386) ├─node(728)─┬─node(911)─┬─node(1110)─┬─bash(1121)───pstree(242065) │ │ │ ├─bash(11587)───create_process(32019)───create_process(32020) │ │ │ ├─{node}(1111) │ │ │ ├─{node}(1112) │ │ │ ├─{node}(1113) │ │ │ ├─{node}(1114) │ │ │ ├─{node}(1115) │ │ │ ├─{node}(1116) │ │ │ ├─{node}(1117) │ │ │ ├─{node}(1118) │ │ │ ├─{node}(1119) │ │ │ ├─{node}(1120) │ │ │ ├─{node}(1122) │ │ │ └─{node}(11588) │ │ ├─node(241465)─┬─{node}(241466) │ │ │ ├─{node}(241467) │ │ │ ├─{node}(241468) │ │ │ ├─{node}(241469) │ │ │ ├─{node}(241470) │ │ │ ├─{node}(241471) │ │ │ ├─{node}(241472) │ │ │ ├─{node}(241473) │ │ │ ├─{node}(241474) │ │ │ ├─{node}(241475) │ │ │ ├─{node}(241476) │ │ │ └─{node}(241483) │ │ ├─node(241484)─┬─{node}(241485) │ │ │ ├─{node}(241486) │ │ │ ├─{node}(241487) │ │ │ ├─{node}(241488) │ │ │ ├─{node}(241489) │ │ │ ├─{node}(241490) │ │ │ ├─{node}(241491) │ │ │ ├─{node}(241492) │ │ │ ├─{node}(241493) │ │ │ ├─{node}(241494) │ │ │ ├─{node}(241496) │ │ │ └─{node}(241497) │ │ ├─{node}(913) │ │ ├─{node}(914) │ │ ├─{node}(915) │ │ ├─{node}(916) │ │ ├─{node}(917) │ │ ├─{node}(918) │ │ ├─{node}(919) │ │ ├─{node}(920) │ │ ├─{node}(921) │ │ └─{node}(922) │ ├─{node}(826) │ ├─{node}(827) │ ├─{node}(828) │ ├─{node}(829) │ ├─{node}(830) │ ├─{node}(857) │ ├─{node}(901) │ ├─{node}(902) │ ├─{node}(903) │ └─{node}(904) ├─polkitd(734)─┬─{polkitd}(790) │ ├─{polkitd}(791) │ └─{polkitd}(793) ├─rsyslogd(823)─┬─{rsyslogd}(853) │ ├─{rsyslogd}(854) │ └─{rsyslogd}(855) ├─systemd-journal(314) ├─systemd-logind(741) ├─systemd-network(560) ├─systemd-resolve(577) ├─systemd-timesyn(588)───{systemd-timesyn}(699) ├─systemd-udevd(380) ├─udisksd(743)─┬─{udisksd}(759) │ ├─{udisksd}(760) │ ├─{udisksd}(762) │ ├─{udisksd}(819) │ └─{udisksd}(847) ├─unattended-upgr(780)───{unattended-upgr}(859) └─upowerd(4275)─┬─{upowerd}(4277) ├─{upowerd}(4278) └─{upowerd}(4279)- ps command with tree format:
ps axfOUTPUT
c@c:~/cos3105$ ps axf PID TTY STAT TIME COMMAND 2 ? S 0:00 [kthreadd] 3 ? S 0:00 \_ [pool_workqueue_release] 4 ? I< 0:00 \_ [kworker/R-rcu_g] 5 ? I< 0:00 \_ [kworker/R-rcu_p] 6 ? I< 0:00 \_ [kworker/R-slub_] 7 ? I< 0:00 \_ [kworker/R-netns] 10 ? I< 0:00 \_ [kworker/0:0H-events_highpri] 11 ? I 0:00 \_ [kworker/u4:0-ext4-rsv-conversion] 12 ? I< 0:00 \_ [kworker/R-mm_pe] 13 ? I 0:00 \_ [rcu_tasks_kthread] 14 ? I 0:00 \_ [rcu_tasks_rude_kthread] 15 ? I 0:00 \_ [rcu_tasks_trace_kthread] 16 ? S 0:01 \_ [ksoftirqd/0] 17 ? I 0:17 \_ [rcu_preempt] 18 ? S 0:01 \_ [migration/0] 19 ? S 0:00 \_ [idle_inject/0] 20 ? S 0:00 \_ [cpuhp/0] 21 ? S 0:00 \_ [cpuhp/1] 22 ? S 0:00 \_ [idle_inject/1] 23 ? S 0:01 \_ [migration/1] 24 ? S 0:03 \_ [ksoftirqd/1] 26 ? I< 0:02 \_ [kworker/1:0H-kblockd] 29 ? S 0:00 \_ [kdevtmpfs] 30 ? I< 0:00 \_ [kworker/R-inet_] 32 ? S 0:00 \_ [kauditd] 33 ? S 0:00 \_ [khungtaskd] 34 ? S 0:00 \_ [oom_reaper] 36 ? I< 0:00 \_ [kworker/R-write] 37 ? S 0:06 \_ [kcompactd0] 38 ? SN 0:00 \_ [ksmd] 40 ? SN 0:00 \_ [khugepaged] 41 ? I< 0:00 \_ [kworker/R-kinte] 42 ? I< 0:00 \_ [kworker/R-kbloc] 43 ? I< 0:00 \_ [kworker/R-blkcg] 44 ? S 0:00 \_ [irq/9-acpi] 45 ? I< 0:00 \_ [kworker/R-tpm_d] 46 ? I< 0:00 \_ [kworker/R-ata_s] 47 ? I< 0:00 \_ [kworker/R-md] 48 ? I< 0:00 \_ [kworker/R-md_bi] 49 ? I< 0:00 \_ [kworker/R-edac-] 50 ? I< 0:00 \_ [kworker/R-devfr] 51 ? S 0:00 \_ [watchdogd] 54 ? S 0:00 \_ [kswapd0] 55 ? S 0:00 \_ [ecryptfs-kthread] 56 ? I< 0:00 \_ [kworker/R-kthro] 57 ? I< 0:00 \_ [kworker/R-acpi_] 59 ? S 0:00 \_ [scsi_eh_0] 60 ? I< 0:00 \_ [kworker/R-scsi_] 61 ? S 0:00 \_ [scsi_eh_1] 62 ? I< 0:00 \_ [kworker/R-scsi_] 65 ? I< 0:00 \_ [kworker/R-mld] 66 ? I< 0:00 \_ [kworker/R-ipv6_] 73 ? I< 0:00 \_ [kworker/R-kstrp] 75 ? I< 0:00 \_ [kworker/u7:0] 76 ? I< 0:00 \_ [kworker/u8:0] 77 ? I< 0:00 \_ [kworker/u9:0] 82 ? I< 0:00 \_ [kworker/R-crypt] 93 ? I< 0:00 \_ [kworker/R-charg] 120 ? I< 0:02 \_ [kworker/0:1H-kblockd] 161 ? S 0:00 \_ [scsi_eh_2] 162 ? I< 0:00 \_ [kworker/R-scsi_] 176 ? I< 0:00 \_ [kworker/R-kdmfl] 206 ? I< 0:00 \_ [kworker/R-raid5] 229 ? I< 0:00 \_ [kworker/1:2H-kblockd] 246 ? S 0:04 \_ [jbd2/dm-0-8] 247 ? I< 0:00 \_ [kworker/R-ext4-] 309 ? S 0:00 \_ [psimon] 342 ? I< 0:00 \_ [kworker/R-kmpat] 344 ? I< 0:00 \_ [kworker/R-kmpat] 367 ? I 0:00 \_ [kworker/u4:1-ext4-rsv-conversion] 394 ? S 0:00 \_ [psimon] 474 ? S 0:00 \_ [irq/18-vmwgfx] 476 ? I< 0:00 \_ [kworker/R-ttm] 479 ? S 0:00 \_ [jbd2/sda2-8] 480 ? I< 0:00 \_ [kworker/R-ext4-] 707 ? I< 0:00 \_ [kworker/R-cfg80] 103557 ? I< 0:00 \_ [kworker/R-tls-s] 179147 ? I 1:35 \_ [kworker/1:0-events] 204808 ? I 0:00 \_ [kworker/u5:3-flush-252:0] 221214 ? I 0:30 \_ [kworker/1:2-events] 235923 ? I 0:00 \_ [kworker/u5:1-events_unbound] 238601 ? I 0:00 \_ [kworker/u6:1-events_power_efficient] 238672 ? I 0:00 \_ [kworker/u5:0-events_unbound] 240464 ? I 0:02 \_ [kworker/0:0-events] 241453 ? I 0:00 \_ [kworker/u6:2-events_unbound] 241458 ? I 0:00 \_ [kworker/0:2-cgroup_destroy] 241459 ? I 0:00 \_ [kworker/u6:4-flush-252:0] 241706 ? I 0:00 \_ [kworker/1:1] 1 ? Ss 0:05 /sbin/init 314 ? S<s 0:01 /usr/lib/systemd/systemd-journald 365 ? SLsl 0:13 /sbin/multipathd -d -s 380 ? Ss 0:00 /usr/lib/systemd/systemd-udevd 560 ? Ss 0:00 /usr/lib/systemd/systemd-networkd 577 ? Ss 0:00 /usr/lib/systemd/systemd-resolved 588 ? Ssl 0:00 /usr/lib/systemd/systemd-timesyncd 728 ? Ssl 0:00 /usr/lib/code-server/lib/node /usr/lib/code-server 911 ? Sl 1:38 \_ /usr/lib/code-server/lib/node /usr/lib/code-server/out/node/entry 1110 ? Sl 2:27 \_ /usr/lib/code-server/lib/node /usr/lib/code-server/lib/vscode/out/bootstrap-fork --type=ptyHost --logsPath /home/c/.local/share/code-server/logs/20250824T125250 1121 pts/0 Ss 0:00 | \_ /bin/bash --init-file /usr/lib/code-server/lib/vscode/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh 242203 pts/0 R+ 0:00 | | \_ ps axf 11587 pts/1 Ss 0:00 | \_ /bin/bash 32019 pts/1 S+ 0:00 | \_ ./create_process 32020 pts/1 S+ 0:00 | \_ ./create_process 241465 ? Sl 0:08 \_ /usr/lib/code-server/lib/node --dns-result-order=ipv4first /usr/lib/code-server/lib/vscode/out/bootstrap-fork --type=extensionHost --transformURIs --useHostProxy=false 241484 ? Sl 0:00 \_ /usr/lib/code-server/lib/node /usr/lib/code-server/lib/vscode/out/bootstrap-fork --type=fileWatcher 729 ? Ss 0:01 @dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only 734 ? Ssl 0:02 /usr/lib/polkit-1/polkitd --no-debug 741 ? Ss 0:00 /usr/lib/systemd/systemd-logind 743 ? Ssl 0:02 /usr/libexec/udisks2/udisksd 780 ? Ssl 0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal 816 ? Ssl 0:00 /usr/sbin/ModemManager 823 ? Ssl 0:00 /usr/sbin/rsyslogd -n -iNONE 873 ? Ss 0:00 /usr/sbin/cron -f -P 882 tty1 Ss+ 0:00 /sbin/agetty -o -p -- \u --noclear - linux 4275 ? Ssl 0:05 /usr/libexec/upowerd- Show specific process tree:
- pstree PID
pstree 1OUTPUT
c@c:~/cos3105$ pstree 1systemd─┬─ModemManager───3*[{ModemManager}] ├─agetty ├─cron ├─dbus-daemon ├─multipathd───6*[{multipathd}] ├─node─┬─node─┬─node─┬─bash───pstree │ │ │ ├─bash───create_process───create_process │ │ │ └─12*[{node}] │ │ ├─2*[node───12*[{node}]] │ │ └─10*[{node}] │ └─10*[{node}] ├─polkitd───3*[{polkitd}] ├─rsyslogd───3*[{rsyslogd}] ├─systemd-journal ├─systemd-logind ├─systemd-network ├─systemd-resolve ├─systemd-timesyn───{systemd-timesyn} ├─systemd-udevd ├─udisksd───5*[{udisksd}] ├─unattended-upgr───{unattended-upgr} └─upowerd───3*[{upowerd}]Process : Create Orphan Process
Section titled “Process : Create Orphan Process”#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main(){ pid_t p; p=fork(); if(p==0) { sleep(5); //child goes to sleep and in the mean time parent terminates printf("I am child having PID %d\n",getpid()); printf("My parent PID is %d\n",getppid()); } else { printf("I am parent having PID %d\n",getpid()); printf("My child PID is %d\n",p); }}OUTPUT
Process : Create Zombie Process
Section titled “Process : Create Zombie Process”#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main(){ pid_t t; t=fork(); if(t==0) { printf("Child having id %d\n",getpid()); } else { printf("Parent having id %d\n",getpid()); sleep(15); // Parent sleeps. Run the ps command during this time }}OUTPUT
Process : Prevent Zombie process by wait()
Section titled “Process : Prevent Zombie process by wait()”#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <sys/wait.h>int main(){ pid_t p; printf("before fork\n"); p=fork(); if(p==0)//child { printf("I am child having id %d\n",getpid()); printf("My parent's id is %d\n",getppid()); } else//parent { wait(NULL); printf("My child's id is %d\n",p); printf("I am parent having id %d\n",getpid()); } printf("Common\n");}OUTPUT

Process : Simulate context switch among process
Section titled “Process : Simulate context switch among process”#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#include <signal.h>#include <sys/types.h>#include <sched.h>
void process_task(const char* name, int task_id, int duration) { printf("Process %s (PID: %d) started\n", name, getpid());
for (int i = 0; i < duration; i++) { printf("Process %s: Step %d/%d (PID: %d)\n", name, i + 1, duration, getpid()); sleep(1);
// Simulate voluntary context switch by calling sched_yield() if (i < duration - 1) { printf("Process %s yielding CPU...\n", name); sched_yield(); } }
printf("Process %s (PID: %d) completed\n", name, getpid());}
void demonstrate_context_info() { printf("\nContext Switch Information:\n"); printf("==========================\n"); printf("Parent PID: %d\n", getppid()); printf("Current PID: %d\n", getpid()); printf("Process Group ID: %d\n", getpgrp());
// Show some context information printf("User ID: %d\n", getuid()); printf("Group ID: %d\n", getgid());}
int main() { printf("Process Context Switch Demonstration\n"); printf("====================================\n");
demonstrate_context_info();
pid_t pid1, pid2, pid3; int status;
// Create first child process pid1 = fork(); if (pid1 == 0) { // Child process 1 process_task("Task-A", 1, 3); exit(0); } else if (pid1 < 0) { perror("Fork failed"); exit(1); }
// Create second child process pid2 = fork(); if (pid2 == 0) { // Child process 2 process_task("Task-B", 2, 4); exit(0); } else if (pid2 < 0) { perror("Fork failed"); exit(1); }
// Create third child process pid3 = fork(); if (pid3 == 0) { // Child process 3 process_task("Task-C", 3, 2); exit(0); } else if (pid3 < 0) { perror("Fork failed"); exit(1); }
// Parent process monitors children printf("\nParent process (PID: %d) monitoring children...\n", getpid());
// Wait for all children to complete for (int i = 0; i < 3; i++) { pid_t finished_pid = wait(&status); printf("Child process %d finished with status %d\n", finished_pid, WEXITSTATUS(status)); }
printf("\nAll processes completed. Context switching demonstration finished.\n");
return 0;}OUTPUT
c@c:~/cos3105$ ./context_switch_among_processProcess Context Switch Demonstration====================================
Context Switch Information:==========================Parent PID: 1088Current PID: 25636Process Group ID: 25636User ID: 1000Group ID: 1000Process Task-A (PID: 25638) startedProcess Task-A: Step 1/3 (PID: 25638)
Parent process (PID: 25636) monitoring children...Process Task-B (PID: 25639) startedProcess Task-B: Step 1/4 (PID: 25639)Process Task-C (PID: 25640) startedProcess Task-C: Step 1/2 (PID: 25640)Process Task-A yielding CPU...Process Task-C yielding CPU...Process Task-A: Step 2/3 (PID: 25638)Process Task-C: Step 2/2 (PID: 25640)Process Task-B yielding CPU...Process Task-B: Step 2/4 (PID: 25639)Process Task-A yielding CPU...Process Task-B yielding CPU...Process Task-C (PID: 25640) completedProcess Task-A: Step 3/3 (PID: 25638)Process Task-B: Step 3/4 (PID: 25639)Child process 25640 finished with status 0Process Task-A (PID: 25638) completedProcess Task-B yielding CPU...Process Task-B: Step 4/4 (PID: 25639)Child process 25638 finished with status 0Process Task-B (PID: 25639) completedChild process 25639 finished with status 0
All processes completed. Context switching demonstration finished.