Operating System Lab — Complete Programs

Save as os_lab_programs.html. Code blocks are escaped so C headers show correctly.

1. Process Creation using fork(), getpid(), getppid(), wait()

File Name: fork_process.c
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid < 0) {
        printf("Fork failed!\n");
    } else if (pid == 0) {
        printf("Child Process: PID = %d, PPID = %d\n", getpid(), getppid());
    } else {
        wait(NULL);
        printf("Parent Process: PID = %d, Child PID = %d\n", getpid(), pid);
    }
    return 0;
}
gcc fork_process.c -o fork_process && ./fork_process
Sample Output: Child Process: PID = 5123, PPID = 5122 Parent Process: PID = 5122, Child PID = 5123

2. Multithreading

File Name: multithread.c
#include <stdio.h>
#include <pthread.h>

void* show(void* arg) {
    printf("Thread %d is running\n", *(int*)arg);
    return NULL;
}

int main() {
    pthread_t t1, t2;
    int a = 1, b = 2;
    pthread_create(&t1, NULL, show, &a);
    pthread_create(&t2, NULL, show, &b);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("Main thread finished\n");
    return 0;
}
gcc multithread.c -o multithread -lpthread && ./multithread
Sample Output: Thread 1 is running Thread 2 is running Main thread finished

3. Banker's Algorithm (Deadlock Avoidance)

File Name: banker.c
#include <stdio.h>

int main() {
    int n, m, i, j, k;
    printf("Enter number of processes: ");
    scanf("%d", &n);
    printf("Enter number of resources: ");
    scanf("%d", &m);
    int alloc[n][m], max[n][m], avail[m], need[n][m], finish[n];
    printf("Enter Allocation Matrix:\n");
    for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&alloc[i][j]);
    printf("Enter Max Matrix:\n");
    for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&max[i][j]);
    printf("Enter Available Resources: ");
    for(j=0;j<m;j++) scanf("%d",&avail[j]);

    for(i=0;i<n;i++){
        for(j=0;j<m;j++) need[i][j]=max[i][j]-alloc[i][j];
        finish[i]=0;
    }

    int safe[n], idx=0, flag;
    for(k=0;k<n;k++){
        for(i=0;i<n;i++){
            if(!finish[i]){
                flag=1;
                for(j=0;j<m;j++) if(need[i][j] > avail[j]) { flag=0; break; }
                if(flag){
                    for(j=0;j<m;j++) avail[j]+=alloc[i][j];
                    safe[idx++]=i;
                    finish[i]=1;
                }
            }
        }
    }

    flag=1;
    for(i=0;i<n;i++) if(!finish[i]) flag=0;
    if(flag){
        printf("Safe Sequence: ");
        for(i=0;i<n;i++) printf("P%d ", safe[i]);
    } else printf("System not in safe state");
    return 0;
}
gcc banker.c -o banker && ./banker
Sample Output: Safe Sequence: P1 P3 P4 P0 P2

4. CPU Scheduling Algorithms

Four common scheduling examples: FCFS, SJF, Priority, Round Robin. Save each code block into its own file.

(a) FCFS Scheduling — fcfs.c

#include <stdio.h>

int main() {
    int n, bt[20], wt[20], tat[20], i;
    float awt=0, atat=0;
    printf("Enter number of processes: ");
    scanf("%d",&n);
    printf("Enter burst times:\n");
    for(i=0;i<n;i++) scanf("%d",&bt[i]);
    wt[0]=0;
    for(i=1;i<n;i++) wt[i]=wt[i-1]+bt[i-1];
    printf("\nProcess\tBT\tWT\tTAT\n");
    for(i=0;i<n;i++) {
        tat[i]=bt[i]+wt[i];
        awt+=wt[i]; atat+=tat[i];
        printf("%d\t%d\t%d\t%d\n",i+1,bt[i],wt[i],tat[i]);
    }
    printf("\nAverage WT=%.2f, Average TAT=%.2f\n",awt/n,atat/n);
    return 0;
}
gcc fcfs.c -o fcfs && ./fcfs

(b) SJF Scheduling — sjf.c

#include <stdio.h>

int main() {
    int n, bt[20], p[20], wt[20], tat[20], i, j, pos, temp;
    float awt=0, atat=0;
    printf("Enter number of processes: ");
    scanf("%d",&n);
    printf("Enter burst times:\n");
    for(i=0;i<n;i++) { scanf("%d",&bt[i]); p[i]=i+1; }
    for(i=0;i<n;i++) {
        pos=i;
        for(j=i+1;j<n;j++) if(bt[j]<bt[pos]) pos=j;
        temp=bt[i]; bt[i]=bt[pos]; bt[pos]=temp;
        temp=p[i]; p[i]=p[pos]; p[pos]=temp;
    }
    wt[0]=0;
    for(i=1;i<n;i++) wt[i]=wt[i-1]+bt[i-1];
    printf("\nProcess\tBT\tWT\tTAT\n");
    for(i=0;i<n;i++) {
        tat[i]=bt[i]+wt[i];
        awt+=wt[i]; atat+=tat[i];
        printf("%d\t%d\t%d\t%d\n",p[i],bt[i],wt[i],tat[i]);
    }
    printf("\nAverage WT=%.2f, Average TAT=%.2f\n",awt/n,atat/n);
    return 0;
}
gcc sjf.c -o sjf && ./sjf

(c) Priority Scheduling — priority.c

#include <stdio.h>

int main() {
    int n, bt[20], p[20], pr[20], wt[20], tat[20], i, j, pos, temp;
    float awt=0, atat=0;
    printf("Enter number of processes: ");
    scanf("%d",&n);
    printf("Enter burst time and priority:\n");
    for(i=0;i<n;i++) { scanf("%d%d",&bt[i],&pr[i]); p[i]=i+1; }
    for(i=0;i<n;i++) {
        pos=i;
        for(j=i+1;j<n;j++) if(pr[j]<pr[pos]) pos=j;
        temp=pr[i]; pr[i]=pr[pos]; pr[pos]=temp;
        temp=bt[i]; bt[i]=bt[pos]; bt[pos]=temp;
        temp=p[i]; p[i]=p[pos]; p[pos]=temp;
    }
    wt[0]=0;
    for(i=1;i<n;i++) wt[i]=wt[i-1]+bt[i-1];
    printf("\nProcess\tPriority\tBT\tWT\tTAT\n");
    for(i=0;i<n;i++) {
        tat[i]=bt[i]+wt[i];
        awt+=wt[i]; atat+=tat[i];
        printf("%d\t%d\t\t%d\t%d\t%d\n",p[i],pr[i],bt[i],wt[i],tat[i]);
    }
    printf("\nAverage WT=%.2f, Average TAT=%.2f\n",awt/n,atat/n);
    return 0;
}
gcc priority.c -o priority && ./priority

(d) Round Robin Scheduling — roundrobin.c

#include <stdio.h>

int main() {
    int n, bt[10], rem[10], wt[10]={0}, tat[10], tq, time=0, i, done;
    printf("Enter number of processes: ");
    scanf("%d",&n);
    printf("Enter burst times:\n");
    for(i=0;i<n;i++){ scanf("%d",&bt[i]); rem[i]=bt[i]; }
    printf("Enter time quantum: ");
    scanf("%d",&tq);
    do {
        done=1;
        for(i=0;i<n;i++){
            if(rem[i]>0){
                done=0;
                if(rem[i]>tq){ time+=tq; rem[i]-=tq; }
                else { time+=rem[i]; wt[i]=time-bt[i]; rem[i]=0; }
            }
        }
    } while(!done);
    float awt=0, atat=0;
    printf("\nProcess\tBT\tWT\tTAT\n");
    for(i=0;i<n;i++){
        tat[i]=bt[i]+wt[i];
        awt+=wt[i]; atat+=tat[i];
        printf("%d\t%d\t%d\t%d\n",i+1,bt[i],wt[i],tat[i]);
    }
    printf("\nAverage WT=%.2f, Average TAT=%.2f\n",awt/n,atat/n);
    return 0;
}
gcc roundrobin.c -o roundrobin && ./roundrobin

5. Page Replacement Algorithms

Three variants: FIFO, LRU and LFU.

(a) FIFO Page Replacement — fifo.c

#include <stdio.h>

int main() {
    int frames, pages[30], n, count=0, temp[10], flag, faults=0;
    printf("Enter number of frames: ");
    scanf("%d",&frames);
    printf("Enter number of pages: ");
    scanf("%d",&n);
    printf("Enter reference string: ");
    for(int m=0;m<n;m++) scanf("%d",&pages[m]);
    for(int m=0;m<frames;m++) temp[m]=-1;
    for(int m=0;m<n;m++) {
        flag=0;
        for(int i=0;i<frames;i++) if(temp[i]==pages[m]) flag=1;
        if(flag==0){
            temp[count%frames]=pages[m];
            count++; faults++;
        }
    }
    printf("\nTotal Page Faults = %d\n", faults);
    return 0;
}
gcc fifo.c -o fifo && ./fifo

(b) LRU Page Replacement — lru.c

#include <stdio.h>

int main() {
    int n, frames;
    printf("Enter number of frames: ");
    scanf("%d",&frames);
    printf("Enter number of pages: ");
    scanf("%d",&n);
    int pages[n];
    printf("Enter reference string: ");
    for(int i=0;i<n;i++) scanf("%d",&pages[i]);
    int temp[frames];
    int count[frames];
    for(int i=0;i<frames;i++) { temp[i]=-1; count[i]=0; }
    int faults=0;
    for(int i=0;i<n;i++) {
        int flag=0;
        for(int j=0;j<frames;j++) {
            if(temp[j]==pages[i]) { flag=1; count[j]=i; break; }
        }
        if(flag==0) {
            int min=0;
            for(int j=1;j<frames;j++) if(count[j]<count[min]) min=j;
            temp[min]=pages[i];
            count[min]=i;
            faults++;
        }
    }
    printf("\nTotal Page Faults = %d\n",faults);
    return 0;
}
gcc lru.c -o lru && ./lru

(c) LFU Page Replacement — lfu.c

#include <stdio.h>

int main(){
    int n, frames;
    printf("Enter number of frames: ");
    scanf("%d",&frames);
    printf("Enter number of pages: ");
    scanf("%d",&n);
    int pages[n];
    printf("Enter reference string: ");
    for(int i=0;i<n;i++) scanf("%d",&pages[i]);
    int temp[frames], freq[frames];
    for(int i=0;i<frames;i++) { temp[i]=-1; freq[i]=0; }
    int faults=0;
    for(int i=0;i<n;i++){
        int flag=0;
        for(int j=0;j<frames;j++){
            if(temp[j]==pages[i]){
                flag=1; freq[j]++; break;
            }
        }
        if(flag==0){
            int min=0;
            for(int j=1;j<frames;j++) if(freq[j]<freq[min]) min=j;
            temp[min]=pages[i];
            freq[min]=1;
            faults++;
        }
    }
    printf("\nTotal Page Faults = %d\n",faults);
    return 0;
}
gcc lfu.c -o lfu && ./lfu

6. Memory Management Policies

Two common allocation strategies: Best Fit and Worst Fit.

(a) Best Fit — bestfit.c

#include <stdio.h>

int main(){
    int b[10], p[10], nb, np, i, j;
    printf("Enter number of blocks: ");
    scanf("%d",&nb);
    printf("Enter block sizes: ");
    for(i=0;i<nb;i++) scanf("%d",&b[i]);
    printf("Enter number of processes: ");
    scanf("%d",&np);
    printf("Enter process sizes: ");
    for(i=0;i<np;i++) scanf("%d",&p[i]);
    int alloc[np];
    for(i=0;i<np;i++) alloc[i]=-1;
    for(i=0;i<np;i++){
        int best=-1;
        for(j=0;j<nb;j++){
            if(b[j]>=p[i]){
                if(best==-1 || b[j]<b[best]) best=j;
            }
        }
        if(best!=-1){
            alloc[i]=best;
            b[best]-=p[i];
        }
    }
    printf("\nProcess\tSize\tBlock\n");
    for(i=0;i<np;i++){
        if(alloc[i]!=-1)
            printf("%d\t%d\t%d\n",i+1,p[i],alloc[i]+1);
        else
            printf("%d\t%d\tNot Allocated\n",i+1,p[i]);
    }
    return 0;
}
gcc bestfit.c -o bestfit && ./bestfit

(b) Worst Fit — worstfit.c

#include <stdio.h>

int main(){
    int b[10], p[10], nb, np, i, j;
    printf("Enter number of blocks: ");
    scanf("%d",&nb);
    printf("Enter block sizes: ");
    for(i=0;i<nb;i++) scanf("%d",&b[i]);
    printf("Enter number of processes: ");
    scanf("%d",&np);
    printf("Enter process sizes: ");
    for(i=0;i<np;i++) scanf("%d",&p[i]);
    int alloc[np];
    for(i=0;i<np;i++) alloc[i]=-1;
    for(i=0;i<np;i++){
        int worst=-1;
        for(j=0;j<nb;j++){
            if(b[j]>=p[i]){
                if(worst==-1 || b[j]>b[worst]) worst=j;
            }
        }
        if(worst!=-1){
            alloc[i]=worst;
            b[worst]-=p[i];
        }
    }
    printf("\nProcess\tSize\tBlock\n");
    for(i=0;i<np;i++){
        if(alloc[i]!=-1)
            printf("%d\t%d\t%d\n",i+1,p[i],alloc[i]+1);
        else
            printf("%d\t%d\tNot Allocated\n",i+1,p[i]);
    }
    return 0;
}
gcc worstfit.c -o worstfit && ./worstfit

Compilation & Execution Summary

mkdir cla_lab && cd cla_lab
# create files (use your editor):
# nano fork_process.c  (paste code), repeat for other files
# compile each program, e.g.:
gcc fork_process.c -o fork_process
./fork_process
# list files:
ls -l
# clear terminal
clear
  
Tip: use -lpthread when compiling pthread programs. For interactive programs provide inputs as prompted.

7. Basic Linux Commands

Useful terminal commands while working on OS Lab programs.

# Navigate into a folder
cd os_lab

# Create an empty file
touch sample.c

# Create and edit a file using nano editor
nano sample.c

# Rename a file
mv sample.c main.c

# Copy a file
cp main.c backup_main.c

# Remove a file
rm backup_main.c

# Create nested directories
mkdir -p projects/os

# Move file to a folder
mv main.c projects/os/

# View file contents
cat projects/os/main.c

# Append text to a file
echo "// Hello World" >> projects/os/main.c

# List files and folders
ls        # simple list
ls -l     # detailed list
ls -a     # show hidden files

# Show current directory
pwd

# Clear screen
clear

# Compile a C file
gcc main.c -o main

# Run program
./main

# Show running processes
ps

# View manual page for a command
man gcc