Operating Systems Lab Manuel 3
Operating Systems Lab Manuel 3
ⓘ
Operating Systems Lab Manual
Name : _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Major: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Group: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
1 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Description : The ls command lists the files and directories in the current directory.
• Usage : ls [options] [directory]
• Examples :
◦ ls : Lists files and directories in the current directory.
◦ ls [directory] : Lists files and directories in the specified directory.
◦ ls -l : Lists files and directories with detailed information (permissions, owner,
size, etc.).
◦ ls -a : Lists all files, including hidden files (those starting with a dot).
Exercise :
Use the ls command to list the contents of the root directory / and write them
down.
2. cd : Change Directory.
Exercise:
Use the cd command to change the current directory to /usr/bin/ , try and guess
what is this directory?!
2 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Description : The pwd command displays the current working directory path.
• Usage : pwd
• Examples :
◦ pwd : Prints the full path of the current directory, e.g., /home/user/Documents .
Exercise:
Use the pwd command to print the current working directory path and write it down.
Exercise:
Use the mkdir command to create a new directory named cyber and a new directory
named scripts inside it, in the home directory.
3 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Examples :
◦ rmdir old_folder : Removes the directory named old_folder if it is empty.
◦ rmdir -p parent/child : Removes the directory child and its parent parent if
both are empty.
Exercise:
Use the rmdir command to remove the directory cyber/scripts .
• Description : The touch command changes file timestamps or creates an empty file if
it doesn't exist..
• Usage : touch [options] file
• Examples :
◦ touch file.txt : Creates an empty file named file.txt .
◦ touch -a file.txt : Changes the access timestamp of the file.
◦ touch -m file.txt : Changes the modification timestamp of the file.
Exercise:
Use the touch command to create a new file named notes.md in the home directory.
7. rm : Remove File.
Exercise:
Use the rm command to remove the file notes.md from the home directory.
4 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Examples :
◦ cp file.txt new_file.txt : Copies the file file.txt to new_file.txt .
◦ cp -r dir new_dir : Copies the directory dir and its contents recursively to
new_dir .
Exercise:
Use the cp command to copy the file .zshrc to a new directory named backups .
Exercise:
Make a new file in the home directory named notes.md and move it to the backups
directory and rename it to readme.md .
5 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Description: grep searches for patterns within files and displays matching lines.
• Usage: grep [options] pattern [file...]
• Examples:
◦ grep 'search_term' file.txt : Searches for search_term in file.txt .
◦ grep -r 'search_term' directory/ : Recursively searches for search_term in
directory/ .
Exercise :
Use the grep command to search for the string touch in the .history file.
Exercise :
Use the find command to find the file named grub in the /etc directory, Do you
know what is this file?!
6 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Exercise :
Use the cat command to concatenate the .zshrc and .bashrc files into
combinedrc.txt , and display it.
Exercise :
Use the whatis command to learn about the more and less commands, and write
down there brief description.
7 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Exercise :
Use the df command to see how mush disk space is used in the home directory.
• Description : uptime displays the current time, how long the system has been
running,the number of users, and system load averages.
• Usage : uptime
• Examples :
◦ uptime : Displays the current system uptime and load averages.
◦ uptime -p : Displays the current system uptime in pretty format.
Exercise :
Use the uptime command to find out how long the system has been running.
• Description : wget and curl are command-line tools for downloading files from the
internet.
• Usage : wget [options] url or curl [options] url
• Examples :
◦ wget https://example.com/file.zip : Downloads the file file.zip from the
internet.
◦ curl -O https://example.com/file.zip : Downloads the file file.zip from the
internet.
Exercise:
Use the wget or curl command to download the https://
raw.githubusercontent.com/Al-aqua/op-lab-man/main/absolutely-not-a-virus file
from the internet. what is the content of the file?
8 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Exercise :
Use the apt command to install the vim package. what is vim ?
9 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
A shell script is a text file containing a series of commands that the shell can execute. Scripts
can include commands, variables, loops, and conditionals to perform complex tasks.
Create a new file with a .sh extension touch first_script.sh and open it in any text
editor.
The shebang (#!) at the top of the file tells the system which interpreter to use. For bash,
use:
#!/bin/bash
#!/bin/bash
echo "Hello, World!"
chmod +x first_script.sh
10 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
./first_script.sh
3. Variables
#!/bin/bash
name="John Doe"
echo "My name is $name"
4. User Input
User input is data that is provided by the user when the script is run.
#!/bin/bash
read -p "Enter your name: " name
echo "Hello, $name!"
5. Conditional Statements
Conditional statements allow you to perform different actions based on different conditions.
#!/bin/bash
read -p "Enter a number: " num
if [ $num -gt 0 ]; then
echo "$num is positive"
elif [ $num -lt 0 ]; then
echo "$num is negative"
else
echo "$num is zero"
fi
6. Loops
for Loops
11 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#!/bin/bash
for i in {1..10}; do
echo "Number: $i"
done
while Loops
#!/bin/bash
i=1
while [ $i -le 10 ]; do
echo "Number: $i"
i=$((i + 1))
done
7. Functions
#!/bin/bash
function greet() {
echo "Hello, $1!"
}
greet "John Doe"
greet "Joe Mama"
8. Script Arguments
#!/bin/bash
echo "Script name: $0"
echo "Argument 1: $1"
echo "Argument 2: $2"
9. Practical Examples
Backup Script
12 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#!/bin/bash
backup_dir="/backup"
mkdir -p $backup_dir
cp -r /home/user/documents $backup_dir
echo "Backup completed!"
Exercise :
Assignment :
13 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Users: Accounts used to log into the system. Each user has a unique ID (UID).
• Groups: Collections of users with common permissions. Each group has a unique ID
(GID).
2. Creating Users
Usage:
3. Managing Passwords
Usage:
14 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
4. Modifying Users
Usage:
5. Deleting Users
Usage:
Usage:
15 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Usage:
who and w
finger
Usage:
8. Best Practices
• Use Strong Passwords: Ensure all user accounts have strong, unique passwords.
• Regularly Audit User Accounts: Periodically review user accounts and permissions.
• Limit sudo Access: Only grant sudo access to trusted users.
• Remove Inactive Users: Delete or disable accounts that are no longer needed.
16 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
2. XFS
17 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Directory Structure
The Linux directory structure is hierarchical, resembling an inverted tree. The topmost
directory is called the root directory and is denoted by a forward slash (/). Below the root,
the file system branches into various directories, each serving a specific purpose.
• / (Root): The base of the file system hierarchy. All other directories and files
stem from here.
• /bin : Essential user binaries (executables) needed for system booting and
single-user mode.
• /boot : Files required for booting the system, including the kernel and
bootloader configuration files.
• /dev : Device files representing hardware components and peripherals.
• /etc : Configuration files for the system and installed applications.
• /home : Home directories for individual users. Each user has a personal directory
under /home .
• /lib : Shared libraries needed by binaries in /bin and /sbin .
• /mnt : Mount point for temporarily mounted file systems.
• /opt : Optional software packages and third-party applications.
• /proc : Virtual file system providing process and kernel information.
• /root : Home directory for the root (superuser).
• /sbin : System binaries essential for system administration.
• /srv : Data for services provided by the system.
• /tmp : Temporary files created by the system and applications.
• /usr : User programs and utilities.
• /var : Variable data files, such as logs, mail spools, and temporary files.
File Types
In Linux, everything is considered a file, including hardware devices and processes. The file
types are identified using the ls -l command, which lists files and their details.
• Regular Files ( - ): The most common type, representing data files, text files, scripts,
and binaries.
18 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
File Permissions
File permissions in Linux are a critical aspect of system security and access control. They
determine who can read, write, or execute a file. Understanding how to view and modify
these permissions is essential for managing files and maintaining a secure system.
Each file and directory has a set of permissions associated with three categories of users:
These permissions are displayed using the ls -l command, which shows a 10-character
string representing the permissions and file type:
ls -l
Example output:
-rwxr-xr--
19 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
◦ - : Regular file
◦ d : Directory
◦ l : Symbolic link
◦ b : Block device
◦ c : Character device
◦ s : Socket
◦ p : Pipe
• The next nine characters are the permissions, divided into three groups of three:
In the example above, the file is a regular file ( - ), the owner has read, write, and execute
permissions ( rwx ), the group has read and execute permissions ( r-x ), and others have
read-only permissions ( r-- ).
You can change file permissions using the chmod command in two modes: symbolic and
numeric.
Symbolic Mode:
• Uses letters to represent the user category ( u for owner, g for group, o for others, a
for all) and permissions ( r, w, x ).
• + adds a permission, - removes a permission, and = sets a permission.
Examples:
Numeric Mode:
• Uses a three-digit octal number to represent permissions. Each digit is a sum of values:
read (4), write (2), and execute (1).
20 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Example:
chmod 755 filename # Sets rwx for owner (4+2+1=7), r-x for group (4+1=5),
and r-x for others (4+1=5)
chmod 644 filename # Sets rw- for owner (4+2=6), r-- for group (4), and r--
for others (4)
chmod 700 filename # Sets rwx for owner (4+2+1=7), --- for group (0), and
--- for others (0)
Special Permissions
Special permissions add additional control for executable files and directories.
• When applied to an executable file, allows users to execute the file with the file owner's
privileges.
• Represented by an s in the owner's execute position ( rws ).
Example:
• When applied to an executable file, allows users to execute the file with the file group's
privileges.
• When applied to a directory, files created within the directory inherit the group
ownership.
• Represented by an s in the group's execute position ( r-s ).
Example:
Sticky Bit:
• When applied to a directory, ensures that only the file owner can delete or rename files
within that directory.
• Represented by a t in the others' execute position ( rwt ).
Example:
21 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
chmod +t directory
Viewing Permissions:
ls -l displays the permissions, owner, group, and other details of files and directories.
Example:
ls -l
// Output
-rw-r--r-- 1 user group 1234 Jan 1 12:34 file.txt
Modifying Permissions:
Examples:
Understanding umask
The umask (user file creation mode mask) command determines the default permissions for
new files and directories. It acts as a filter that removes specific permissions when new files
and directories are created.
22 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Calculating umask:
• The default permissions for new files are 666 (read and write for all).
• The default permissions for new directories are 777 (read, write, and execute for all).
• The umask value is subtracted from these defaults to determine the final permissions.
umask
• To set a new umask value, use the umask command followed by the desired value.
umask 022
Example Calculation:
• If the umask is 022, the default permissions for a new file will be 644 (666 - 022),
resulting in read and write permissions for the owner, and read-only permissions for
the group and others.
• For a new directory, the permissions will be 755 (777 - 022), resulting in read, write, and
execute permissions for the owner, and read and execute permissions for the group
and others.
ACLs provide a more flexible permission mechanism than the traditional file permissions.
They allow you to set permissions for individual users or groups on a per-file or per-
directory basis.
Using ACLs:
getfacl filename
23 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
SELinux (Security-Enhanced Linux) and AppArmor are MAC systems that provide additional
security by enforcing policies that restrict how programs can access files and resources.
SELinux:
• Enforces policies that define how processes interact with files, devices, and other
processes.
• Policies are defined in terms of contexts, consisting of user, role, type, and level.
Basic Commands:
AppArmor:
Basic Commands:
24 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
File Encryption
Encrypting files ensures that unauthorized users cannot access the data without the
appropriate decryption key. One of the most widely used tools for file encryption in Linux is
gpg (GNU Privacy Guard).
• Encrypting a File:
gpg -c filename
This command prompts you to enter a passphrase. The encrypted file is saved with a .gpg
extension.
• Decrypting a File:
gpg -d filename.gpg
Encrypting entire file systems provides a higher level of security by ensuring that all data
stored within the file system is encrypted. LUKS (Linux Unified Key Setup) is a standard for
disk encryption.
Secure Deletion
When files are deleted in a typical manner, the data is not completely erased from the disk
and can be recovered using forensic tools. Secure deletion ensures that data is
irrecoverable.
shred -u filename
25 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Note: Traditional secure deletion tools may not be effective on SSDs due to wear
leveling. Using encryption and secure erase commands provided by the SSD
manufacturer is recommended.
Creating Backups
Creating regular backups ensures that you can restore your system to a previous state in
case of data loss, hardware failure, or other unforeseen events. Linux offers several
powerful tools for this purpose.
26 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
◦ --delete : Deletes files in the destination that are not present in the source.
Recovering Data
In the event of data loss, having a solid recovery strategy can help minimize downtime and
data loss.
There are a lot of tools that can streamline data backups recovery and automate it like
TimeShift.
• testdisk : A powerful tool for recovering lost partitions and making non-booting disks
bootable again.
sudo testdisk
27 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
sudo photorec
28 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
What is a Process?
A process is a running instance of a program. It is an active entity that requires system
resources such as CPU time, memory, and input/output (I/O) operations to execute its
instructions. In Linux, every process is assigned a unique Process ID (PID), which is used to
identify and manage it.
Key Concepts:
• Parent and Child Processes: n Linux, every process is spawned by another process,
known as the parent process. The new process is called a child process. The init or
systemd process is the ancestor of all processes and has a PID of 1.
Process creation
Process creation in Linux is a fundamental concept that involves duplicating an existing
process (the parent) to create a new process (the child). This is primarily achieved using
system calls like fork() , exec() , and wait() . Let's explore these in more detail with
examples.
29 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
[!NOTE] We will be using the c programming language to explore these concepts. The c
and c++ compiler( gcc ) comes installed by default in Linux. to compile the code, use
The fork() system call is used to create a new process by duplicating the current process.
The newly created process is called the child process, and the original process is called the
parent process. After a fork() call, two processes will execute: the parent and the child.
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
// Error in fork
fprintf(stderr, "Fork Failed\n");
return 1;
} else if (pid == 0) {
// Child process
printf("This is the Child Process. PID: %d\n", getpid());
} else {
// Parent process
printf("This is the Parent Process. PID: %d, Child PID: %d\n",
getpid(), pid);
}
return 0;
}
Explanation:
• The fork() call returns twice: once in the parent process and once in the child
process.
◦ In the child process, fork() returns 0 .
◦ In the parent process, fork() returns the PID of the child process.
• The getpid() function returns the PID of the current process.
• The program prints different messages depending on whether it's running in the
30 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Expected Output:
After creating a child process, it is common to replace the child’s process image with a new
program using the exec() family of functions. This does not create a new process but
replaces the current process's memory with a new program.
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
// Error in fork
fprintf(stderr, "Fork Failed\n");
return 1;
} else if (pid == 0) {
// Child process
printf("Child Process - Executing ls command\n");
execlp("/bin/ls", "ls", NULL);
// If exec fails
printf("Exec Failed\n");
} else {
// Parent process
wait(NULL);
printf("Child Complete\n");
}
return 0;
}
Explanation:
• After fork() , the child process uses execlp() to execute the ls command.
• If exec() succeeds, the original child process is replaced by ls , and the following
code ( printf("Exec Failed\n") ) is not executed.
• The parent process waits for the child to complete using wait() .
31 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Expected Output:
The wait() system call makes the parent process wait until all of its child processes have
finished executing. This is useful for ensuring that the parent does not exit before the child,
or to capture the child's exit status.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
// Error in fork
fprintf(stderr, "Fork Failed\n");
return 1;
} else if (pid == 0) {
// Child process
printf("Child Process - Executing ls command\n");
execlp("/bin/ls", "ls", NULL);
// If exec fails
printf("Exec Failed\n");
} else {
// Parent process
wait(NULL);
printf("Child Complete\n");
}
return 0;
}
Explanation:
• The child process prints its PID and then simulates some work by sleeping for 2
seconds.
• The parent process calls wait() , which pauses the parent until the child process
completes.
• After the child finishes, the parent resumes and prints a completion message.
32 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Expected Output:
The exit() system call is used to terminate a process. This is useful for terminating a
process in an orderly manner.
33 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
// Error in fork
fprintf(stderr, "Fork Failed\n");
return 1;
} else if (pid == 0) {
// Child process
printf("Child Process. PID: %d\n", getpid());
return 0;
}
Explanation:
34 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
◦ The wait() function captures more than just whether the child exited; it also
captures how the child exited, including whether it was terminated by a signal or
completed normally with an exit() call.
3. Checking the Exit Status:
◦ WIFEXITED(status) : This macro checks whether the child process terminated
normally via exit() or \_exit() . If it did, the macro returns a non-zero value.
◦ WEXITSTATUS(status) : If WIFEXITED(status) is true, this macro extracts the
actual exit status code provided by the child process via exit() . In this case, it
retrieves the 1 that was passed to exit(1) .
Expected Output:
Managing Processes
Linux provides several commands to manage and monitor processes:
35 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• The load average represents the average number of processes waiting for CPU time
over 1, 5, and 15-minute intervals.
• High load averages indicate that processes are spending more time waiting for CPU
resources, which may signal a need for optimization or resource scaling.
• strace : Traces system calls and signals received by a process, useful for debugging
and understanding process behavior.
strace -p PID
36 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
1. What is a Thread?
A thread is the smallest unit of execution within a process. Unlike processes, which are
independent execution units containing their own memory space, threads are part of a
process and share the same memory space. This shared environment makes threads more
lightweight than processes because they require fewer resources to create and maintain.
37 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Advantages of Threads:
Creating a Thread
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
pthread_t thread;
int result;
pthread_join(thread, NULL);
printf("Thread has finished execution.\n");
return 0;
}
38 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
5. Thread Synchronization
Thread synchronization is critical in multi-threaded programming to ensure that threads do
not interfere with each other while accessing shared resources. Synchronization techniques
help maintain data integrity and prevent race conditions.
1. Race Condition
A race condition occurs when two or more threads attempt to change shared data at the
same time, leading to unexpected and incorrect results. Consider the following example
where multiple threads increment a shared counter:
39 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <pthread.h>
#include <stdio.h>
int counter = 0;
int main() {
pthread_t threads[10];
Problem: Here, you might expect the final counter value to be 1000000 , but due to the race
condition, it might be less. This is because threads can interrupt each other while modifying
the counter, leading to lost updates.
To prevent race conditions, you can use a mutex (short for "mutual exclusion"). A mutex
ensures that only one thread can execute a piece of code at a time.
40 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <pthread.h>
#include <stdio.h>
int counter = 0;
pthread_mutex_t lock;
int main() {
pthread_t threads[10];
pthread_mutex_init(&lock, NULL); // Initialize the mutex
Solution: Using a mutex ensures that only one thread can increment the counter at a time,
preventing race conditions. Now, the final counter value should be 1000000 as expected.
3. Deadlock
A deadlock occurs when two or more threads are waiting for each other to release a
resource, causing them to be stuck forever. Consider this example:
41 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_lock(&lock2);
printf("Thread 1: Locked lock2\n");
pthread_mutex_unlock(&lock2);
pthread_mutex_unlock(&lock1);
return NULL;
}
pthread_mutex_lock(&lock1);
printf("Thread 2: Locked lock1\n");
pthread_mutex_unlock(&lock1);
pthread_mutex_unlock(&lock2);
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock1, NULL);
pthread_mutex_init(&lock2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock1);
pthread_mutex_destroy(&lock2);
return 0;
}
42 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Explanation:
• Avoid Nested Locks: Minimize the use of nested locks and ensure that all threads
acquire locks in a consistent order.
• Lock Ordering: Always acquire locks in a fixed global order to prevent circular waiting.
if (pthread_mutex_trylock(&lock2) == 0) {
// Successfully locked lock2
} else {
// Could not lock lock2, handle accordingly
}
4. Condition Variables
Condition variables are used to signal between threads. They allow one or more threads to
wait until a particular condition occurs. Condition variables are always used with a mutex to
avoid race conditions.
In the producer-consumer problem, one or more producer threads generate data and put it
into a buffer, while one or more consumer threads take data out of the buffer and process
it.
43 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond_producer, cond_consumer;
pthread_mutex_lock(&mutex);
while (count == BUFFER_SIZE) {
pthread_cond_wait(&cond_producer, &mutex); // Wait if buffer is
full
}
buffer[count] = item;
count++;
printf("Produced: %d\n", item);
item = buffer[--count];
printf("Consumed: %d\n", item);
int main() {
44 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_producer, NULL);
pthread_cond_init(&cond_consumer, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_producer);
pthread_cond_destroy(&cond_consumer);
return 0;
}
Explanation:
• Producer: Produces an item and places it into the buffer. If the buffer is full, the
producer waits until there is space.
• Consumer: Consumes an item from the buffer. If the buffer is empty, the consumer
waits until there is data to consume.
• Condition Variables: cond_producer is used to signal the producer that there is space
in the buffer, and cond_consumer is used to signal the consumer that there is data to
consume.
This ensures smooth operation without overfilling the buffer or consuming non-existent
data.
45 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
In this chapter, we will explore different scheduling algorithms, how they work, and their
practical applications in a Linux environment.
Efficient scheduling ensures that CPU and IO-bound processes don't unnecessarily wait for
each other, optimizing overall system performance.
46 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Example: Linux uses preemptive scheduling, but for specific system calls or critical tasks, it may
temporarily switch to non-preemptive mode.
4. Scheduling Algorithms
Let’s dive into the most common CPU scheduling algorithms, how they work, and their
practical implementation:
• How it works: Processes are scheduled in the order they arrive in the ready queue.
• Type: Non-preemptive.
• Pros: Simple and easy to implement.
• Cons: Can lead to long wait times, particularly if the first process in the queue is CPU-
bound (known as the "convoy effect").
Example in C:
47 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
int main() {
int n, i;
printf("Enter number of processes: ");
scanf("%d", &n);
waiting_time[0] = 0;
// Output results
printf("\nProcess\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t\t%d\t\t%d\n", i + 1, burst_time[i], waiting_time[i],
turnaround_time[i]);
}
return 0;
}
Explanation:
48 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
time.
4. Output Results: Display process details along with average waiting and turnaround
times.
• How it works: The process with the shortest burst time is selected next.
• Type: Non-preemptive.
• Pros: Minimizes average waiting time.
• Cons: Can lead to starvation of longer processes.
Example in C:
49 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
int main() {
int n, i, j;
printf("Enter number of processes: ");
scanf("%d", &n);
waiting_time[0] = 0;
// Output results
printf("\nProcess\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t\t%d\t\t%d\n", i + 1, burst_time[i], waiting_time[i],
turnaround_time[i]);
}
50 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
return 0;
}
Explanation:
• How it works: Each process is assigned a priority. The process with the highest priority
is selected next.
• Type: Can be preemptive or non-preemptive.
• Pros: Allows important tasks to be completed first.
• Cons: Can lead to starvation of lower-priority processes.
Example in C
51 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
#define MAX 10
int main() {
int n, i, j;
printf("Enter number of processes: ");
scanf("%d", &n);
temp = priority[i];
priority[i] = priority[j];
priority[j] = temp;
}
}
}
waiting_time[0] = 0;
// Output results
printf("\nProcess\tBurst Time\tPriority\tWaiting Time\tTurnaround Time\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t\t%d\t\t%d\t\t%d\n", i + 1, burst_time[i],
52 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
return 0;
}
Explanation:
1. Input Burst Times and Priorities: Collect burst times and priorities for each process.
2. Sort Processes: Sort processes based on priority.
3. Calculate Waiting Time: Compute waiting time based on sorted order.
4. Calculate Turnaround Time: Calculate turnaround time.
5. Output Results: Display process details, including priorities, and average times.
• How it works: Each process is assigned a fixed time slice (quantum). The CPU cycles
through processes, allocating each a turn.
• Type: Preemptive.
• Pros: Fair distribution of CPU time among processes.
• Cons: Time quantum must be carefully chosen to avoid excessive context switching.
Example in C:
53 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
#define MAX 10
int main() {
int n, i, time_quantum, time = 0, remaining;
printf("Enter number of processes: ");
scanf("%d", &n);
remaining = n;
54 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
// Output results
printf("\nProcess\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t\t%d\t\t%d\n", i + 1, burst_time[i], waiting_time[i],
turnaround_time[i]);
}
return 0;
}
Explanation:
1. Input Burst Times and Time Quantum: Collect burst times and time quantum.
2. Round Robin Simulation: Allocate CPU time in fixed slices.
3. Calculate Waiting and Turnaround Times: Compute times based on the simulation.
4. Output Results: Display process details and average times.
• How it works: Processes are managed in multiple queues based on their behavior and
requirements. The system adjusts process priorities dynamically.
Example in C:
55 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
#include <stdio.h>
#define MAX 10
int main() {
int n, i, time_quantum, time = 0, remaining;
printf("Enter number of processes: ");
scanf("%d", &n);
// Output results
printf("\nProcess\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t\t%d\t\t%d\n", i + 1, burst_time[i], waiting_time[i],
56 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
turnaround_time[i]);
}
printf("\nAverage Waiting Time: %.2f", (float)total_waiting_time / n);
printf("\nAverage Turnaround Time: %.2f", (float)total_turnaround_time
/ n);
return 0;
}
Explanation:
Linux uses a CPU scheduling algorithm called Completely Fair Scheduler (CFS). CFS is
designed to provide fair CPU time to processes while considering their priority and
ensuring that all processes get a reasonable amount of CPU time.
6. Summary
CPU scheduling is fundamental to operating systems, affecting how efficiently processes are
57 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
executed and how resources are allocated. Understanding different algorithms allows
system designers to choose the best approach based on specific needs and constraints. The
choice of scheduling algorithm impacts system performance, user experience, and overall
system efficiency.
• FCFS: Simple but can lead to long wait times for short processes.
• SJN: Reduces average waiting time but may lead to process starvation.
• Priority Scheduling: Can prioritize important tasks but risks starving lower-priority
processes.
• Round Robin: Ensures fair allocation of CPU time among processes but requires
careful selection of time quantum.
• Multilevel Queue: Allows flexibility in scheduling different types of processes but can
be complex to manage.
• Multilevel Feedback Queue: Dynamically adjusts priorities, balancing responsiveness
and fairness.
58 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
2. Memory Hierarchy
Memory in a system can be categorized into multiple levels of hierarchy, each with different
speeds and sizes. At the top is the fastest but smallest memory, and at the bottom is the
slowest but largest.
1. Registers and Cache Memory: Extremely fast, small memory spaces inside the CPU
used to store temporary data.
2. Main Memory (RAM): The physical memory where processes are loaded for
execution.
3. Secondary Storage (HDD/SSD): Used when RAM is not sufficient. This is much slower
but significantly larger in size.
4. Virtual Memory: A technique that allows the system to use part of the secondary
storage as if it were RAM, enabling processes to use more memory than physically
available.
59 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
4. Paging
Paging is one of the most commonly used memory management techniques in modern
operating systems. It eliminates the problem of fragmentation by dividing memory into
fixed-size blocks called pages (for virtual memory) and frames (for physical memory).
• Page Table: The operating system maintains a page table to track which pages of a
process are in which frames of physical memory.
• Page Faults: If a process accesses a page that is not currently in memory, a page fault
occurs, and the operating system must load the page from disk.
Advantages of Paging:
In Linux, a multi-level paging system is used for virtual memory management. Processes are
not aware of physical memory addresses, and the kernel handles mapping between virtual
and physical memory.
60 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
5. Segmentation
In segmentation, memory is divided into logical segments such as the code, data, and
stack of a process. Each segment has a varying size based on the process's needs.
• Segment Table: Similar to the page table, the segment table keeps track of the base
and limit addresses for each segment of a process.
In contrast to paging, segmentation is concerned with dividing programs into logical units
that reflect how the programmer views memory (e.g., a code segment, a data segment).
6. Virtual Memory
Virtual memory allows an operating system to use secondary storage (like an SSD or HDD)
as an extension of RAM. This allows systems to run processes that exceed the size of
physical memory.
• Demand Paging: Pages are only loaded into memory when they are needed by the
process.
• Page Replacement Algorithms: When memory is full, the OS needs to decide which
pages to swap out. Some common page replacement algorithms are:
7. Memory Fragmentation
Fragmentation occurs when memory is used inefficiently, leading to wasted memory space.
There are two types of fragmentation:
61 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
8. Memory Protection
Memory protection is vital to ensure that one process cannot interfere with the memory
space of another process. Operating systems enforce memory protection through
techniques such as base and limit registers.
In Linux, hardware mechanisms like segmentation and paging are used to protect memory.
9. Conclusion
Memory management is essential for the efficient operation of any system. Operating
systems use a variety of techniques to allocate, protect, and optimize memory usage.
Understanding how paging, segmentation, virtual memory, and page replacement
algorithms work is critical for optimizing system performance and resource allocation.
By implementing the memory allocator and understanding these concepts, students can
appreciate the real-world challenges operating systems face in managing memory
efficiently.
62 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
• Multitasking: Multiple processes can run simultaneously, each believing it has its own
isolated address space.
• Efficient Memory Utilization: Unused memory portions of a program can be kept on
disk until needed, freeing up RAM for other processes.
• Memory Protection: Each process operates in its own virtual address space,
preventing one process from interfering with another.
1. Paging: Dividing virtual memory into fixed-size blocks called pages and physical
memory into frames of the same size. A page from virtual memory can be loaded into
any free frame in physical memory. The operating system manages this mapping using
a page table.
2. Swapping: When physical memory is full, the OS swaps inactive pages from RAM to
disk storage, which is slower but much larger. This space on disk is called the swap
space.
Every memory address that a program uses is a virtual address, which the operating
63 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
system translates into a physical address using the page table. This translation process
happens during every memory access via the Memory Management Unit (MMU).
When a program runs, its pages are loaded into available frames in RAM. The page table
keeps track of which page is stored in which frame. If a page is not in memory, it results in a
page fault.
A page fault occurs when a process tries to access a page that is not currently in physical
memory. When this happens:
Page faults introduce latency since accessing the disk is much slower than accessing RAM, so
the OS aims to minimize them.
2. LRU (Least Recently Used): The page that hasn’t been used for the longest time is
64 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
removed.
3. Optimal Page Replacement: Replaces the page that will not be used for the longest
time in the future. Though this provides the best results, it is generally theoretical since
future page accesses are unknown.
Each algorithm has its strengths and weaknesses, and different operating systems use
different approaches based on their requirements.
2. Efficient Use of Memory: Programs don’t need to be fully loaded into physical
memory. Only the necessary pages are loaded on demand, allowing more processes to
run concurrently.
3. Larger Address Space: Virtual memory allows processes to use more memory than is
physically available by using the swap space on disk.
4. Swapping: Less frequently used pages are swapped to disk, freeing up RAM for more
critical tasks.
1. Performance Overhead: Accessing a page from disk is much slower than accessing it
from RAM, leading to a performance hit when too many page faults occur. This
condition is known as thrashing.
2. Disk I/O Bottleneck: Heavy reliance on swap space can lead to increased disk input/
output operations, slowing down the system.
65 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
Unlike paging, segmentation presents the memory to processes in a way that aligns with
how programmers structure programs, making it more intuitive. However, segmentation can
lead to external fragmentation, where free memory is scattered across the system.
• Demand Paging: Pages are only loaded into memory when they are needed by the
program.
• Swappiness: This parameter controls the tendency of the Linux kernel to use swap
space. A lower value reduces swapping, while a higher value increases it.
• Multi-Level Page Tables: Linux uses a multi-level page table structure to map large
amounts of virtual memory to physical memory efficiently.
66 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
1. Simulating Virtual Memory: Set up an array to represent the virtual memory and
another array for physical memory (frames).
2. Page Table Management: Maintain a page table to map virtual pages to physical
frames.
3. Page Fault Handling: When a page fault occurs, load the required page from virtual
memory into a free frame or replace an existing page using a chosen page
replacement algorithm.
4. Swapping: If no free frames are available, the page replacement algorithm selects a
page to be swapped out.
10. Conclusion
Virtual memory is an essential component of modern operating systems, allowing them to
run programs that require more memory than what is physically available. By using
techniques like paging and segmentation, virtual memory ensures efficient use of resources,
isolates processes, and provides a flexible environment for multitasking.
Understanding how virtual memory works, including page replacement algorithms and
swapping, is crucial for optimizing system performance and effectively managing memory
resources.
67 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
1. Introduction to OS Security
Security in an operating system (OS) is crucial for protecting system resources like files,
processes, and hardware from unauthorized access and malicious activities. In Linux,
security is enforced through access control, user authentication, and network security.
Linux employs a permission system that defines access for the owner, group, and others.
Permissions include:
ls -l filename
68 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
This allows the owner to read, write, and execute the file, while others can only read and
execute it.
Files and directories have an owner and an associated group. Ownership can be modified
using the chown command:
Properly managing file permissions and ownership is critical for maintaining system security.
3. User Authentication
User authentication ensures that only authorized users can access the system.
Linux stores password hashes in the /etc/shadow file. Authentication occurs by comparing
the user's input with the stored hash.
SSH (Secure Shell) provides a secure method for remote login to a Linux system. SSH can be
configured for password-based or key-based authentication, with key-based authentication
being more secure.
ssh-keygen -t rsa
69 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
ssh-copy-id username@server
ssh username@server
By default, SSH listens on port 22, but you can change this for additional security by editing
the /etc/ssh/sshd_config file.
4. Firewalls in Linux
A firewall controls incoming and outgoing network traffic, enhancing system security by
allowing or denying access based on predefined rules. Linux supports multiple firewall tools,
including iptables and ufw (Uncomplicated Firewall).
ufw is a user-friendly firewall tool available on many Linux distributions. It simplifies the
process of managing firewall rules.
70 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
For more granular control over network traffic, iptables can be used. It is a powerful
firewall tool that allows administrators to set specific rules for handling traffic based on IP
addresses, ports, and protocols.
While ufw is easier to manage, iptables offers more flexibility for advanced users.
71 of 72 6�29�25, 12:42 PM
Operating systems lab manuel http:��localhost:3000�print�html
By properly configuring firewalls and SSH, these threats can be mitigated effectively.
72 of 72 6�29�25, 12:42 PM