Lab Manual OSD
Lab Manual OSD
Prerequisites
1. Backup your important data before proceeding with installation.
2. Ensure you have installation media for both Windows and Linux (e.g., USB drives,
ISO files).
3. The system should have a supported architecture for both OSes (usually 64-bit).
bash
sudo update-grub
This command should detect both Linux and Windows installations and add them to the
GRUB bootloader.
3. Reboot the system. When the system starts, the GRUB menu should now show
options for both Windows and Linux.
Troubleshooting Tips
Windows Boot Manager Overwrites GRUB: If we ever reinstall Windows after
Linux installation, the Windows boot manager will overwrite GRUB. In this case, we
need to repair the GRUB bootloader using a live Linux USB. You can chroot into
your Linux installation and reinstall GRUB.
Example steps to restore GRUB:
1. Boot from a Linux live USB.
2. Open a terminal and mount root partition:
bash
sudo mount /dev/sdXn /mnt # Replace sdXn with root partition
bash
sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind
/sys /mnt/sys
5. Reinstall GRUB:
bash
grub-install /dev/sda # Replace with your disk if different update-grub
bash
exit sudo reboot
Secure Boot: On some systems, Secure Boot may prevent the installation of Linux.
You can disable Secure Boot in the BIOS/UEFI settings if you encounter issues.
Conclusion
By following the above steps, one should have a functioning dual-boot system with both
Windows and Linux.
Experiment No 2:
Aim: Study of various Linux commands.
bash
ls # List files in the current directory ls -l # List files with detailed information (long listing) ls
-a # List all files, including hidden files (those starting with '.') ls /path/to/directory # List
files in a specific directory
bash
cd /path/to/directory # Change to a specific directory cd ~ # Change to the home directory cd ..
# Move one level up
bash
cp file1.txt /path/to/destination/ # Copy a file cp -r directory1 /path/to/destination/
# Copy a directory recursively
bash
mv file1.txt /path/to/destination/ # Move a file to another directory mv old_name.txt
new_name.txt # Rename a file
bash
m file1.txt # Remove a file rm -r directory1 # Remove a directory and its contents rm -f
file1.txt # Force remove a file without prompting
bash
touch file1.txt # Create a new empty file
bash
mkdir directory_name # Create a directory mkdir -p parent/child # Create parent and child
directories
bash
rmdir directory_name # Remove an empty directory
bash
cat file1.txt # Display the contents of a file
bash
more file1.txt # View the content of a file one page at a time
bash
less file1.txt # View a file with better navigation
bash
head file1.txt # Show the first 10 lines of a file head -n 20 file1.txt # Show the first 20 lines
bash
tail file1.txt # Show the last 10 lines of a file tail -f file1.txt # Continuously show new lines
added to a file (useful for log files)
grep: Search for a pattern in a file
bash
grep "pattern" file1.txt # Search for "pattern" in the file grep -r "pattern" . # Recursively
search for "pattern" in the current directory
bash
wc file1.txt # Count lines, words, and characters in a file wc -l file1.txt # Count the number of
lines
bash
top # View real-time system resource usage and process information
bash
ps aux # Show all processes running on the system ps -ef # Another format for displaying
process information
bash
df # Display disk space usage for all mounted filesystems df -h # Show disk space in human-
readable format (e.g., GB, MB)
bash
du -sh /path/to/directory # Show total disk usage of a directory du -h /path/to/directory # Show
disk usage for each subdirectory (human-readable format)
bash
free -h # Show free and used memory in human-readable format
bash
uptime # Display system uptime, number of users, and load average
uname: Show system information
bash
uname -a # Display detailed information about the system (kernel, architecture, etc.)
4. Process Management
kill: Terminate processes
bash
kill <PID> # Kill a process by its PID (Process ID) killall process_name # Kill all processes
by name
bash
bg <job_number> # Move a specific job to the background
bash
fg <job_number> # Bring a specific job to the foreground
bash
nohup command & # Run a command in the background even after logout
5. Networking Commands
ping: Test network connectivity to a host
bash
ping google.com # Ping a website to test connectivity
bash
ifconfig # Display network interface configurations
ip: Show or manipulate routing, devices, and tunnels (modern alternative to ifconfig)
bash
ip addr show # Display IP address information for all interfaces ip link show # Show network
interface status
bash
wget http://example.com/file.zip # Download a file from a URL
bash
curl http://example.com # Fetch a URL curl -O http://example.com/file # Download a file
bash
sudo fdisk /dev/sda # Partition the disk /dev/sda
bash
sudo mount /dev/sda1 /mnt # Mount the first partition of /dev/sda to /mnt
bash
sudo umount /mnt # Unmount the /mnt directory
bash
sudo adduser new_user # Add a new user
bash
sudo passwd user_name # Change the password for the user
bash
whoami # Show the current logged-in username
Conclusion
The above Linux commands provide a foundation for working with files, processes, networks,
system information, and disk management.
Experiment No 3
Aim: Study of init program and configuration of inittab file.
The init program is a core component of many Unix-like operating systems, including Linux.
It is the first process started by the kernel during booting and remains running as the last
process when the system shuts down. The init program is responsible for starting system
processes, managing runlevels, and handling system startup and shutdown. It reads
configuration files that specify which processes to start at boot time.
In traditional Linux systems, the configuration of the init program is typically managed by
the /etc/inittab file. This file defines the system’s runlevels, specifies which processes should
be run at each runlevel, and controls the behavior of init.
Note: Many modern Linux distributions, such as those using systemd, have replaced the
traditional SysVinit system, and inittab might no longer be used. However, understanding init
and inittab is still important for legacy systems or distributions that use the older init system.
Key Concepts
1. init Program:
o The init process is the ancestor of all processes in Unix-like systems and is
typically assigned the process ID (PID) of 1.
o It manages the startup and shutdown sequence of the system.
o The init program is responsible for transitioning between different runlevels
(system states).
2. Runlevels: Runlevels represent different states of the system, and different processes
are started or stopped depending on the runlevel. Common runlevels include:
o Runlevel 0: Halt (shutdown the system).
o Runlevel 1: Single-user mode (used for administrative tasks).
o Runlevel 3: Multi-user mode with networking (no GUI).
o Runlevel 5: Multi-user mode with GUI (graphical user interface).
o Runlevel 6: Reboot (restart the system).
3. /etc/inittab File: The /etc/inittab file is the configuration file that defines the behavior
of the init program. It specifies the system's runlevels, which processes to start, and
how to handle various system events like shutdown or reboot.
Program
# Default runlevel
id:5:initdefault:
Conclusion
The init program is crucial for managing the system startup, shutdown, and the execution of
processes at various runlevels. The /etc/inittab file is where you configure the system’s
behavior, including defining the default runlevel and specifying which processes should run
at each runlevel.
Experiment No 4:
Aim: System Administration in Linux: Managing Users & Resources
1. User management using /etc/passwd, /etc/shadow, /etc/login.defs,
and /etc/default/useradd.
2. Boot configuration using /boot/grub/grub.conf and /etc/lilo.conf.
Each of these files plays a vital role in system administration, and by interacting with them,
we can configure user accounts, password policies, default user settings, and boot options.
Step 1: Managing User Accounts
1. /etc/passwd: User Account Information
The /etc/passwd file contains essential details about user accounts. It defines attributes such
as usernames, user IDs (UID), group IDs (GID), home directories, and default shells.
You can manually edit the /etc/passwd file or use user management commands
like useradd, usermod, and userdel.
Example: Add a User via useradd (updates /etc/passwd)
bash
sudo useradd -m -s /bin/bash john_doe
Example output:
ruby
john_doe:x:1001:1001::/home/john_doe:/bin/bash
bash
sudo passwd john_doe
After changing the password, you can verify the /etc/shadow entry:
bash
sudo cat /etc/shadow | grep john_doe
Example output:
swift
john_doe:$6$abcdefg$xyz1234.....:17956:0:99999:7:::
bash
sudo nano /etc/login.defs
This configuration will force users to change their passwords every 90 days, allow password
changes after 7 days, and warn users 7 days before the password expires.
4. /etc/default/useradd: Default User Creation Settings
The /etc/default/useradd file defines default settings for new users, such as their home
directory, shell, and user group.
Example: Modify default settings for useradd
Edit /etc/default/useradd to change the default shell and home directory:
bash
sudo nano /etc/default/useradd
Example:
bash
HOME=/home SHELL=/bin/bash USERGROUPS_ENAB=yes
This will set the default shell for new users to /bin/bash and ensure that a user-specific group
is created.
bash
sudo nano /boot/grub/grub.conf
bash
default=0 timeout=5 title Linux (2.6.32-431.el6.i686) root (hd0,0) kernel /vmlinuz-2.6.32-
431.el6.i686 ro root=LABEL=/ rhgb quiet initrd /initrd-2.6.32-431.el6.i686.img
bash
sudo nano /etc/lilo.conf
bash
sudo lilo
bash
sudo useradd -m -s /bin/bash alice sudo passwd alice
bash
cat /etc/passwd | grep alice cat /etc/shadow | grep alice
bash
sudo nano /etc/login.defs
Set:
PASS_MAX_DAYS 90 PASS_MIN_DAYS 7 PASS_WARN_AGE 7
22. Modify Default User Settings in /etc/default/useradd: Set default shell and
user group creation:
bash
sudo nano /etc/default/useradd
Set:
bash
HOME=/home SHELL=/bin/bash USERGROUPS_ENAB=yes
bash
sudo nano /boot/grub/grub.conf
Set:
makefile
default=0 timeout=5
bash
sudo nano /etc/lilo.conf
Set:
javascript
boot=/dev/sda prompt timeout=50 default=Linux image=/boot/vmlinuz-2.6.32-431.el6.i686
label=Linux root=/dev/sda1 read-only
bash
sudo lilo
Conclusion
This program demonstrates key aspects of system administration related to user and resource
management in Linux. The configuration files /etc/passwd, /etc/shadow, /etc/login.defs,
and /etc/default/useradd manage user accounts, authentication policies, and default settings
for user creation. Additionally, the bootloader configuration files
(/boot/grub/grub.conf and /etc/lilo.conf) manage system boot settings.
Experiment No 5
Aim: Study of process management tools, ps, top, chrt, nice tools.
Objective:
The objective of this practical is to familiarize students with commonly used process
management tools in Linux or UNIX systems. These tools allow users to manage and monitor
system processes, prioritize tasks, and obtain detailed information about running processes.
The tools covered in this practical are:
1. ps - Process Status
2. top - Task Manager
3. chrt - Set or Get Scheduling Policy and Priority
4. nice - Start a Process with Modified Scheduling Priority
Prerequisites:
Basic knowledge of Linux/UNIX commands and file system navigation.
Access to a Linux or UNIX-based system with terminal/command-line access.
1. ps (Process Status)
The ps command is used to display information about active processes on the system. This
tool is very useful for monitoring and managing running processes.
Usage:
bash
ps [options]
Common options:
ps: Displays processes running in the current shell.
ps -e or ps -A: Displays all running processes on the system.
ps -u <username>: Displays processes belonging to a specific user.
ps -aux: Displays detailed information about all processes, including processes from
other users.
ps -ef: Displays detailed information in a standardized format.
Example:
1. To view all processes running on the system:
bash
ps -e
bash
ps -aux
bash
ps -u root
bash
ps -eo pid,comm,etime
bash
top
bash
top
While running top, you can monitor system performance and adjust the priority of processes
as needed.
bash
chrt [options] <pid>
Common options:
chrt -p <pid>: Get the scheduling policy and priority of a process with the given PID.
chrt -r <priority> <command>: Run a command with a real-time scheduling policy
and a specified priority.
chrt -o <pid>: Set the process to use FIFO scheduling.
chrt -f <priority> <pid>: Set a process to use a round-robin policy with the specified
priority.
Example:
1. To view the current scheduling policy and priority of a process with PID 12345:
bash
chrt -p 12345
bash
chrt -r 10 ./myprogram
3. To change the scheduling policy of an existing process (e.g., PID 12345) to FIFO:
bash
chrt -o 12345
bash
nice [options] <command>
Common options:
nice -n <priority> <command>: Start a process with the specified priority.
nice -n 10 <command>: Start a process with a lower priority (less CPU time).
Example:
1. To start a program (./myprogram) with a higher priority:
bash
Copy code
nice -n -10 ./myprogram
2. To start a program (./myprogram) with a lower priority:
bash
Copy code
nice -n 10 ./myprogram
3. To change the priority of an already running process, use the renice command:
bash
Copy code
renice -n -5 -p 12345
top Displays real-time information about system processes and resource usage.
Set or get the scheduling policy and priority of processes, especially real-time
chrt
tasks.
Lab Exercise:
Task 1: Use ps to view system processes.
Use the ps -aux command to view all the processes running on your system.
Filter the output by a specific user using ps -u <username>.
Display processes in a custom format (e.g., PID, command, CPU time) using ps -eo
pid,comm,etime.
Task 2: Monitor system performance using top.
Run the top command to monitor your system's performance.
Identify processes using the most CPU and memory resources.
Sort processes by memory and CPU usage.
Task 3: Change process priority using nice and renice.
Start a new process with a low priority using nice -n 10.
Find the PID of an existing process and change its priority using renice.
Task 4: Modify scheduling policy using chrt.
Set the scheduling policy of a process to real-time using chrt.
View the current scheduling policy of a process using chrt -p <pid>.
Run a process with a real-time policy using chrt -r 10 ./myprogram.
Conclusion:
This practical provides hands-on experience with process management tools that are essential
for system administrators and users managing UNIX/Linux systems. Understanding how to
monitor, prioritize, and control processes helps optimize system performance and ensure that
critical tasks get the required CPU time.
Experiment No 6:
Aim: Implement Process creation concept with fork() system call.
Objective:
To understand and implement the concept of process creation in Unix/Linux using the fork()
system call. The fork() system call is used to create a new process by duplicating the calling
process. The child process created by fork() is an exact copy of the parent process, except for
the returned value.
Background:
In Unix/Linux, processes are created using the fork() system call. When fork() is called, it
creates a new process (called the child process) that runs concurrently with the calling
process (called the parent process). After the fork() call, both the parent and child processes
continue execution from the point where the fork() was called, but they can behave
differently based on the return value of fork():
Parent Process: Receives the PID (Process ID) of the child process (a positive
integer).
Child Process: Receives 0.
This allows the parent and child processes to execute different code, depending on the return
value.
Tools/Technologies:
Operating System: Unix/Linux
Programming Language: C (or C++)
Prerequisites:
Basic knowledge of processes in Unix/Linux.
Familiarity with system calls in Unix/Linux, especially fork(), getpid(), and getppid().
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
// Fork the process
pid_t pid = fork();
if (pid < 0) {
// Fork failed
perror("Fork failed");
return 1;
} else if (pid == 0) {
// Child process
printf("Hello from Child Process!\n");
printf("Child PID: %d\n", getpid());
printf("Parent PID: %d\n", getppid());
} else {
// Parent process
printf("Hello from Parent Process!\n");
printf("Parent PID: %d\n", getpid());
printf("Child PID: %d\n", pid);
return 0;
}
bash
gcc process_creation.c -o process_creation
5. Running the Program:
After successful compilation, you can run the program using:
bash
./process_creation
6. Expected Output:
When you run the program, you should see something like the following output (output order
may vary because of concurrent execution of the parent and child processes):
yaml
Hello from Parent Process!
Parent PID: 1234
Child PID: 1235
Hello from Child Process!
Child PID: 1235
Parent PID: 1234
The parent process prints its own PID and the PID of the child process.
The child process prints its own PID and the PID of its parent process (which is the
PID of the parent process).
The order of output may vary because the child and parent processes run concurrently.
7. Understanding Process Creation:
When the fork() is executed, a new process (child) is created, and both processes
continue from the point after fork(). The parent process gets the child’s PID, and the
child process gets 0.
The parent process uses wait() to ensure that it waits for the child process to
complete execution before it terminates, avoiding orphan processes.
8. Further Experimentation:
You can modify this program to observe other behaviors, such as:
Using exec() system calls in the child process to replace the child process with a new
program.
Creating multiple child processes in a loop.
Experimenting with non-blocking waitpid() or wait() for handling child process
termination asynchronously.
Conclusion:
This practical demonstrates how the fork() system call in Unix/Linux works to create a new
process. By creating a child process and differentiating the behavior of the parent and child
processes based on the return value of fork(), one can implement basic process creation and
management.
Experiment No 7
Aim: Implement and compare various CPU scheduling Algorithms.
Objective:
To understand and implement the following CPU scheduling algorithms in a Unix/Linux
environment:
First-Come-First-Serve (FCFS)
Shortest Job Next (SJN) / Shortest Job First (SJF)
Round Robin (RR)
Priority Scheduling (PS)
After implementing these algorithms, you will compare their performance in terms of various
metrics such as:
Turnaround Time
Waiting Time
Throughput
Background:
CPU scheduling is a fundamental part of any operating system. It decides the order in which
processes are executed by the CPU. Different CPU scheduling algorithms are designed to
manage the execution of processes and optimize system performance. Here’s a brief overview
of the algorithms to be implemented:
1. FCFS (First-Come-First-Serve):
o The simplest CPU scheduling algorithm.
o Processes are executed in the order they arrive in the ready queue.
o Can lead to the convoy effect, where short processes have to wait for longer
ones.
2. SJN / SJF (Shortest Job Next / Shortest Job First):
o A non-preemptive algorithm where the process with the shortest burst time is
executed first.
o It minimizes the average waiting time but requires knowledge of the burst
time, which is often not available in real systems.
3. RR (Round Robin):
o A preemptive scheduling algorithm.
o Each process is assigned a fixed time slice (quantum), and the CPU is
allocated to each process in a circular fashion.
o It ensures fair distribution of CPU time.
4. Priority Scheduling (PS):
o Each process is assigned a priority, and the process with the highest priority is
executed first.
o It can be preemptive or non-preemptive.
Steps to Implement and Compare CPU Scheduling Algorithms
1. Create the Data Structure for Processes:
create a structure to represent processes with attributes like Process ID (PID), burst time
(execution time), priority (for priority scheduling), and arrival time.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10
// Define a structure for Process Control Block (PCB)
typedef struct {
int pid; // Process ID
int burst_time; // Burst time of the process
int arrival_time; // Arrival time of the process
int completion_time;// Completion time of the process
int waiting_time; // Waiting time of the process
int turnaround_time;// Turnaround time of the process
int priority; // Priority of the process (for Priority Scheduling)
int remaining_time; // Remaining time (for Round Robin)
} Process;
2. First-Come-First-Serve (FCFS) Implementation:
void fcfs(Process processes[], int n) {
int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;
// FCFS Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}
total_waiting_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
current_time = processes[i].completion_time;
}
// SJF Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}
total_waiting_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
current_time = processes[i].completion_time;
}
// Priority Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}
Objective:
Background:
In a computer system, deadlock occurs when a set of processes are blocked because each process is
holding a resource and waiting for a resource held by another process. The main goal of deadlock
avoidance is to ensure that the system never enters an unsafe state where deadlock could occur.
The Banker's Algorithm is one of the most well-known methods of deadlock avoidance. It
determines whether the system is in a safe state by simulating resource allocation and checking if
there is always a way to allocate resources such that all processes can eventually finish.
The system must know the maximum number of resources each process will need.
Key Terminologies:
1. Safe State: A state in which the system can allocate resources to processes in such a way that
all processes can eventually complete.
2. Unsafe State: A state in which there is no guarantee that all processes can complete,
potentially leading to deadlock.
The allocation matrix, which shows how many resources are allocated to each process.
The maximum matrix, which shows the maximum number of resources each process may
need.
The available vector, which shows the available resources in the system.
#include <stdio.h>
#include <stdbool.h>
#define MAX_PROCESSES 5
#define MAX_RESOURCES 3
// Function prototypes
void calculateNeed();
bool isSafeState();
void printSystemState();
To simulate the system, we will initialize the total resources, allocated resources, and maximum
resources required by each process.
void initializeSystem() {
// Allocation matrix
// Maximum matrix
calculateNeed();
The Need matrix represents the remaining resource needs of each process to finish its execution.
void calculateNeed() {
The isSafeState() function checks if the system is in a safe state by attempting to simulate the
allocation of resources and ensuring that all processes can eventually finish.
bool isSafeState() {
finish[i] = false;
if (!finish[i]) {
canFinish = false;
break;
if (canFinish) {
work[j] += allocation[i][j];
finish[i] = true;
count++;
progress = true;
}
// If no process could make progress, the system is in an unsafe state
if (!progress) {
return false;
return true;
5. Request Resources:
The resourceRequest() function checks if a process can request resources. If the request is valid and
the system remains in a safe state, resources are allocated to the process. If not, the request is
denied.
return false;
return false;
return true;
}
void resourceRequest(int process, int request[]) {
if (checkRequest(process, request)) {
available[i] -= request[i];
allocation[process][i] += request[i];
need[process][i] -= request[i];
if (isSafeState()) {
} else {
available[i] += request[i];
allocation[process][i] -= request[i];
need[process][i] += request[i];
} else {
To visualize the current state of the system, we will implement a function that prints the status of
resources, allocation, and the need matrix.
void printSystemState() {
printf("Available Resources:\n");
for (int i = 0; i < MAX_RESOURCES; i++) {
printf("\nAllocation Matrix:\n");
printf("\n");
printf("\nNeed Matrix:\n");
printf("\n");
Main Function
int main() {
initializeSystem();
printSystemState();
resourceRequest(1, request1);
printSystemState();
return 0;
Expected Output:
Available Resources:
Resource 1: 3
Resource 2: 3
Resource 3: 2
Allocation Matrix:
Process 0: 0 1 0
Process 1: 2 0 0
Process 2: 3 0 2
Process 3: 2 1 1
Process 4: 0 0 2
Need Matrix:
Process 0: 7 4 3
Process 1: 1 2 2
Process 2: 6 0 0
Process 3: 2 1 1
Process 4: 5 3 1
Resource 1: 2
Resource 2: 3
Resource 3: 0
Allocation Matrix:
Process 0: 0 1 0
Process 1: 3 0 2
Process 2: 3 0 2
Process 3: 2 1 1
Process 4: 0 0 2
Need Matrix:
Process 0: 7 4 3
Process 1: 0 2 0
Process 2: 6 0 0
Process 3: 2 1 1
Process 4: 5 3 1
Conclusion:
In this practical, we implemented the Banker's Algorithm for deadlock avoidance. The algorithm
ensures that a system never enters an unsafe state by simulating resource allocation and checking if
all processes can complete. By maintaining matrices for allocated resources, maximum resources,
and available resources, the system can evaluate whether a request can be safely granted and
prevent deadlock.