0% found this document useful (0 votes)
16 views

Lab Manual OSD

Wjeieiei
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

Lab Manual OSD

Wjeieiei
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 44

Experiment No 1

Aim: Making a Dual-Boot System with Linux and Windows


Creating a dual-boot system with both Linux and Windows involves installing both operating
systems on the same machine and configuring them to allow the user to choose which one to
boot into. The process is broken into several steps: preparing the system, installing the first
OS (typically Windows), creating a partition for Linux, installing Linux, and configuring the
bootloader.

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).

Step 1: Install Windows First (If Not Already Installed)


Most systems should have Windows installed first, as Windows doesn't work well when
installed after Linux (Windows overwrites the bootloader).
1. Create a bootable USB for Windows:
 Download the Windows ISO from the official Microsoft website.
 Use a tool like Rufus to create a bootable USB drive from the ISO.
2. Install Windows:
 Boot from the USB drive (you may need to change boot order in BIOS/UEFI
settings).
 During the installation process, you will be asked to choose a partition or disk
for installation. Leave some unallocated space (unformatted space) for Linux
to install later.
 Complete the installation of Windows as instructed.

Step 2: Prepare the System for Linux Installation


1. Create space for Linux:
 After Windows installation, boot into Windows and open the Disk
Management tool (Press Win + X → select "Disk Management").
 Shrink the volume of the Windows partition to create unallocated space for
Linux (at least 20 GB recommended).
2. Create a bootable USB for Linux:
 Download a Linux distribution ISO (Ubuntu, Fedora, Debian, etc.) from the
official website of the distribution.
 Use Rufus or a similar tool to create a bootable USB drive for Linux.

Step 3: Install Linux


1. Boot from the Linux USB:
 Restart your computer and boot from the USB drive containing the Linux
installation image.
 Select "Try Linux" if you want to use the live environment, or directly select
"Install Linux."
2. Partition the disk:
 During the installation process, when asked where to install Linux,
choose Manual Partitioning (this may vary depending on your Linux distro).
 Select the unallocated space you created earlier.
 Create the following partitions for Linux:
 / (root partition): 15-20 GB (ext4 filesystem)
 swap: 2-4 GB (or match the size of your RAM, in the case of
hibernation)
 (Optional) /home partition: remaining space if you want to separate
user files from the system files.
3. Install Linux:
 Proceed with the installation of Linux by selecting the partitions you created.
 Important: Choose the correct bootloader location (usually /dev/sda for the
primary hard drive). This ensures that the Linux bootloader (GRUB) can
manage the boot process and offer a menu to select between Linux and
Windows.
 Continue with the installation process until complete.
4. Reboot the system:
 Once the installation is finished, reboot the computer. You should now see the
GRUB bootloader that allows you to select either Windows or Linux.

Step 4: Configure the GRUB Bootloader (if necessary)


In some cases, the GRUB bootloader may not automatically detect Windows. If Windows
doesn't appear in the boot menu, we can update GRUB to add Windows.
1. Boot into Linux (if GRUB is working).
2. Open a terminal and run the following commands to update GRUB:

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.

Step 5: Test the Dual-Boot System


1. Boot into Linux: Choose Linux from the GRUB menu.
2. Boot into Windows: Restart the computer and choose Windows from the GRUB
menu.

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

3. Mount necessary filesystems:

bash
sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind
/sys /mnt/sys

4. Chroot into your system:


bash
sudo chroot /mnt

5. Reinstall GRUB:

bash
grub-install /dev/sda # Replace with your disk if different update-grub

6. Exit chroot and reboot:

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.

1. File Management Commands


These commands help you manage files and directories in Linux.
 ls: List directory contents

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

 cd: Change directory

bash
cd /path/to/directory # Change to a specific directory cd ~ # Change to the home directory cd ..
# Move one level up

 cp: Copy files or directories

bash
cp file1.txt /path/to/destination/ # Copy a file cp -r directory1 /path/to/destination/
# Copy a directory recursively

 mv: Move or rename files or directories

bash
mv file1.txt /path/to/destination/ # Move a file to another directory mv old_name.txt
new_name.txt # Rename a file

 rm: Remove files or directories

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

 touch: Create an empty file

bash
touch file1.txt # Create a new empty file

 mkdir: Create directories

bash
mkdir directory_name # Create a directory mkdir -p parent/child # Create parent and child
directories

 rmdir: Remove an empty directory

bash
rmdir directory_name # Remove an empty directory

2. File Content Viewing and Manipulation


 cat: Display file content

bash
cat file1.txt # Display the contents of a file

 more: View file content page by page

bash
more file1.txt # View the content of a file one page at a time

 less: Similar to more, but with backward navigation

bash
less file1.txt # View a file with better navigation

 head: View the first few lines of a file

bash
head file1.txt # Show the first 10 lines of a file head -n 20 file1.txt # Show the first 20 lines

 tail: View the last few lines of a file

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

 wc: Count words, lines, and characters in a file

bash
wc file1.txt # Count lines, words, and characters in a file wc -l file1.txt # Count the number of
lines

3. System Information Commands


These commands are used to display system status, information, and statistics.
 top: Display real-time process information

bash
top # View real-time system resource usage and process information

 ps: Display a snapshot of running processes

bash
ps aux # Show all processes running on the system ps -ef # Another format for displaying
process information

 df: Show disk space usage

bash
df # Display disk space usage for all mounted filesystems df -h # Show disk space in human-
readable format (e.g., GB, MB)

 du: Show disk usage of files and directories

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)

 free: Display memory usage

bash
free -h # Show free and used memory in human-readable format

 uptime: Show how long the system has been running

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

 bg: Move a job to the background

bash
bg <job_number> # Move a specific job to the background

 fg: Bring a job to the foreground

bash
fg <job_number> # Bring a specific job to the foreground

 nohup: Run a command in the background and ignore hangup signals

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

 ifconfig: Display or configure network interfaces (older command)

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

 netstat: Display network connections, routing tables, and interface statistics


bash
netstat -tuln # Show active listening ports and associated IP addresses

 wget: Download files from the internet

bash
wget http://example.com/file.zip # Download a file from a URL

 curl: Transfer data from or to a server (supports multiple protocols)

bash
curl http://example.com # Fetch a URL curl -O http://example.com/file # Download a file

6. Disk Management Commands


 fdisk: Partition a disk

bash
sudo fdisk /dev/sda # Partition the disk /dev/sda

 mount: Mount a filesystem

bash
sudo mount /dev/sda1 /mnt # Mount the first partition of /dev/sda to /mnt

 umount: Unmount a filesystem

bash
sudo umount /mnt # Unmount the /mnt directory

7. User Management Commands


 adduser: Add a new user

bash
sudo adduser new_user # Add a new user

 passwd: Change user password

bash
sudo passwd user_name # Change the password for the user

 whoami: Display the current logged-in 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

Step 1: Understand the init Program


The init program runs with a process ID of 1 and is responsible for:
 Starting the system in a specific runl evel.
 Monitoring the system state.
 Handling system shutdown and reboot procedures.
The init program is started by the kernel after the boot process. It then reads the /etc/inittab
file to configure the system.
Checking the init Process:
You can check the current running init process by running the following command:
ps -p 1
The output will show the init program running with PID 1.
Step 2: Understanding the /etc/inittab File
The /etc/inittab file is the main configuration file for init. It specifies the default runlevel and
lists the processes that should be run at different runlevels.
Default Runlevel:
The default runlevel is defined by the initdefault entry in /etc/inittab. It specifies which
runlevel init should start in when the system boots.
Example:
id:5: initdefault:
This means the system will boot into runlevel 5, which is typically the graphical mode
(multi-user with GUI).
Structure of the /etc/inittab File:
Each line in the /etc/inittab file has the following format:
id:runlevel:action:process
 id: A unique identifier for the entry.
 runlevel: The runlevels that the entry applies to.
 action: The action init should take (e.g., run a command, wait for an event, etc.).
 process: The command or process to be executed.
Step 3: Example of a Basic /etc/inittab Configuration
Here is a simple example of the /etc/inittab file:
# /etc/inittab

# Default runlevel
id:5:initdefault:

# System initialization (init process)


si::sysinit:/etc/init.d/rcS

# Getty processes for virtual consoles (console login)


1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4

# Runlevel 5 - Start the graphical login (X server)


x:5:respawn:/etc/init.d/xdm start

# Shutdown entry - to gracefully shut down the system


shutdown:0:wait:/etc/init.d/halt
Explanation of the Entries:
1. id:5:initdefault:
o Sets the default runlevel to 5, which typically corresponds to multi-user mode
with a GUI.
2. si::sysinit:/etc/init.d/rcS
o This line tells init to execute the system initialization script (rcS) during boot.
3. 1:2345:respawn:/sbin/mingetty tty1
o Starts a mingetty process on terminal tty1 in runlevels 2, 3, 4, and 5. mingetty
is a lightweight version of getty for managing login prompts.
4. x:5:respawn:/etc/init.d/xdm start
o In runlevel 5 (which typically indicates a graphical environment), the system
will start the X Display Manager (xdm) to initiate the graphical login screen.
5. shutdown:0:wait:/etc/init.d/halt
o This entry ensures the system gracefully shuts down when entering runlevel 0
(halt state).
Step 4: Modify the /etc/inittab File
To modify the /etc/inittab file, follow these steps:
1. Open the /etc/inittab file with a text editor like nano or vim:
2. sudo nano /etc/inittab
3. Make necessary changes to configure the system’s runlevels and processes. For
example, if you want to set the system to boot into runlevel 3 (multi-user mode with
networking), change the id:5:initdefault: line to:
4. id:3:initdefault:
5. Save the file and exit the editor.
6. Apply changes: To apply changes made to /etc/inittab, you need to reload the init
configuration by executing the following command:
7. sudo init q
This will tell init to re-read the /etc/inittab file and apply any changes immediately.
Step 5: Managing Runlevels with init
The init program can be used to change the system's runlevel. For example:
 To switch to runlevel 3 (multi-user mode with networking):
 sudo init 3
 To switch to runlevel 5 (multi-user mode with GUI):
 sudo init 5
 To shut down the system (runlevel 0):
 sudo init 0
 To reboot the system (runlevel 6):
 sudo init 6

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

 This command creates a new user john_doe with a home


directory /home/john_doe and assigns /bin/bash as the default shell.
To verify, check /etc/passwd:
bash
cat /etc/passwd | grep john_doe

Example output:

ruby
john_doe:x:1001:1001::/home/john_doe:/bin/bash

2. /etc/shadow: Password Information


The /etc/shadow file stores the encrypted passwords of users along with other account-related
details such as password expiration and account locking.
You can change a user's password using passwd:

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:::

This entry contains the encrypted password for john_doe.


3. /etc/login.defs: Login Configuration
The /etc/login.defs file controls login-related configuration like password aging, UID/GID
ranges, and more.
Example: Set password aging limits
In /etc/login.defs, you can define the following parameters:
 PASS_MAX_DAYS: Maximum days before a password must be changed.
 PASS_MIN_DAYS: Minimum days between password changes.
 PASS_WARN_AGE: Days before expiration to warn the user.
Modify /etc/login.defs like this:

bash
sudo nano /etc/login.defs

Set the following:


PASS_MAX_DAYS 90 PASS_MIN_DAYS 7 PASS_WARN_AGE 7

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.

Step 2: Managing Boot Configuration


The boot process in Linux is managed by bootloaders like GRUB and LILO. The
configuration files for each bootloader allow administrators to define boot options, such as
the default kernel to boot, boot parameters, and timeout settings.
1. /boot/grub/grub.conf: GRUB Bootloader Configuration
The /boot/grub/grub.conf file is used by the GRUB bootloader to configure the system's
boot options, including which operating system to boot and what parameters to pass to the
kernel.
Example: Modify GRUB configuration
To modify GRUB settings, open /boot/grub/grub.conf:

bash
sudo nano /boot/grub/grub.conf

Example contents of 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

This configuration specifies:


 default=0: The first boot option will be selected by default.
 timeout=5: The boot menu will wait for 5 seconds before selecting the default
option.
 title: Defines the boot menu entry (e.g., a specific kernel).
 root: The disk and partition where the root file system resides.
 kernel: Specifies the kernel to boot.
 initrd: Specifies the initial RAM disk image to use.
2. /etc/lilo.conf: LILO Bootloader Configuration
For systems using the LILO bootloader, the configuration is stored in /etc/lilo.conf. It
defines the parameters for booting, including the root partition and kernel image.
Example: Modify LILO configuration
Edit /etc/lilo.conf:

bash
sudo nano /etc/lilo.conf

Example contents of lilo.conf:


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

This configuration specifies:


 boot=/dev/sda: The boot device (the first disk).
 prompt: Shows the LILO prompt at boot.
 timeout=50: Wait for 5 seconds before automatically booting.
 default=Linux: The default boot entry is Linux.
 image: Specifies the path to the kernel image.
 root=/dev/sda1: The root filesystem is located on /dev/sda1.
After modifying /etc/lilo.conf, run lilo to apply the changes:

bash
sudo lilo

Complete Example: User Management and Boot Configuration


Here’s a complete example combining both user management and boot configuration:
19. Create a New User:

bash
sudo useradd -m -s /bin/bash alice sudo passwd alice

20. Verify User Information in /etc/passwd and /etc/shadow:

bash
cat /etc/passwd | grep alice cat /etc/shadow | grep alice

21. Modify Login Settings in /etc/login.defs: Open /etc/login.defs and set


password aging:

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

23. Modify GRUB Bootloader Configuration: Edit /boot/grub/grub.conf:

bash
sudo nano /boot/grub/grub.conf
Set:
makefile
default=0 timeout=5

24. Modify LILO Bootloader Configuration (if using


LILO): Edit /etc/lilo.conf:

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

After modifying lilo.conf, apply the changes with:

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

2. To view detailed information about processes:

bash
ps -aux

3. To view processes running under a specific user (e.g., user root):

bash
ps -u root

4. To view processes with a specific format:

bash
ps -eo pid,comm,etime

2. top (Task Manager)


The top command provides a dynamic, real-time view of the processes running on the
system. It updates continuously, providing an ongoing snapshot of the system's activity,
including CPU usage, memory usage, and process details.
Usage:

bash
top

Key Interface Elements:


 PID: Process ID
 USER: User running the process
 %CPU: CPU usage of the process
 %MEM: Memory usage of the process
 TIME+: Total CPU time used by the process
 COMMAND: Name of the command/command line that started the process
Key Commands within top:
 Press q to quit the top interface.
 Press P to sort processes by CPU usage.
 Press M to sort processes by memory usage.
 Press k to kill a process by specifying its PID.
 Press r to renice a process by adjusting its priority.
Example:

bash
top

While running top, you can monitor system performance and adjust the priority of processes
as needed.

3. chrt (Set or Get Scheduling Policy and Priority)


The chrt command is used to set or get the real-time scheduling policy and priority of a
process. This is useful for managing the priority of processes that require more urgent CPU
time.
Usage:

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

2. To run a command with real-time scheduling (e.g., with priority 10):

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

4. nice (Start a Process with Modified Scheduling Priority)


The nice command is used to start a process with a modified CPU scheduling priority. The
priority ranges from -20 (highest priority) to 19 (lowest priority). The default priority is 0.
Usage:

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

Summary of Key Commands and Their Functions:


Command Description

ps Displays the status of active processes.

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.

nice Start a process with a modified priority (affects CPU scheduling).

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().

Steps to Implement Process Creation with fork() in C


1. Create a new C file for the program:
Create a new C file, e.g., process_creation.c, where we will implement the fork() system call.
2. Code Implementation:

#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);

// Wait for child process to finish


wait(NULL);
}

return 0;
}

3. Explanation of the Code:


 fork(): The fork() function is called to create a new child process. It returns a pid_t
(Process ID) value:
o If pid < 0: Fork failed, and we handle the error.
o If pid == 0: This is the child process. It executes the child code block.
o If pid > 0: This is the parent process. It executes the parent code block.
 getpid(): This function returns the Process ID (PID) of the calling process.
 getppid(): This function returns the Parent Process ID (PPID), which is the PID of the
parent process of the current process.
 wait(): The parent process uses wait(NULL) to wait for the child process to finish its
execution before the parent process exits. This helps in synchronizing the parent and
child processes and avoids orphan processes.
4. Compiling the Code:
To compile the code, use the following command:

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;

// Sorting processes based on arrival time


for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (processes[i].arrival_time > processes[j].arrival_time) {
Process temp = processes[i];
processes[i] = processes[j];
processes[j] = temp;
}
}
}

// FCFS Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}

processes[i].waiting_time = current_time - processes[i].arrival_time;


processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
processes[i].completion_time = current_time + processes[i].burst_time;

total_waiting_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;

current_time = processes[i].completion_time;
}

printf("\nFCFS Scheduling Results:\n");


printf("PID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].pid,
processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}
printf("\nAverage Waiting Time: %.2f\n", total_waiting_time / (float)n);
printf("Average Turnaround Time: %.2f\n", total_turnaround_time / (float)n);
}

3. Shortest Job First (SJF) Implementation:

void sjf(Process processes[], int n) {


int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;

// Sorting based on burst time for SJF


for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (processes[i].burst_time > processes[j].burst_time) {
Process temp = processes[i];
processes[i] = processes[j];
processes[j] = temp;
}
}
}

// SJF Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}

processes[i].waiting_time = current_time - processes[i].arrival_time;


processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
processes[i].completion_time = current_time + processes[i].burst_time;

total_waiting_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;

current_time = processes[i].completion_time;
}

printf("\nSJF Scheduling Results:\n");


printf("PID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].pid,
processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}

printf("\nAverage Waiting Time: %.2f\n", total_waiting_time / (float)n);


printf("Average Turnaround Time: %.2f\n", total_turnaround_time / (float)n);
}
4. Round Robin (RR) Implementation:
void round_robin(Process processes[], int n, int quantum) {
int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0, completed = 0;

// Initialize remaining time for each process


for (int i = 0; i < n; i++) {
processes[i].remaining_time = processes[i].burst_time;
}

while (completed < n) {


for (int i = 0; i < n; i++) {
if (processes[i].remaining_time > 0) {
if (processes[i].remaining_time <= quantum) {
current_time += processes[i].remaining_time;
processes[i].remaining_time = 0;
processes[i].turnaround_time = current_time - processes[i].arrival_time;
processes[i].waiting_time = processes[i].turnaround_time -
processes[i].burst_time;
completed++;
} else {
current_time += quantum;
processes[i].remaining_time -= quantum;
}
}
}
}

printf("\nRound Robin Scheduling Results:\n");


printf("PID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].pid,
processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}

printf("\nAverage Waiting Time: %.2f\n", total_waiting_time / (float)n);


printf("Average Turnaround Time: %.2f\n", total_turnaround_time / (float)n);
}
5. Priority Scheduling (PS) Implementation:
void priority_scheduling(Process processes[], int n) {
int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;

// Sorting based on priority (higher value means higher priority)


for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (processes[i].priority < processes[j].priority) {
Process temp = processes[i];
processes[i] = processes[j];
processes[j] = temp;
}
}
}

// Priority Scheduling
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}

processes[i].waiting_time = current_time - processes[i].arrival_time;


processes[i].turnaround_time = processes[i].waiting_time

Conclusion: Thus comparision of various CPU scheduling Algorithms is done successfully.


Experiment No 8

Aim: Implement safety algorithms to avoid deadlock in operating system.

Objective:

To implement and demonstrate deadlock avoidance techniques using safety algorithms in an


operating system. Specifically, we will implement the Banker's Algorithm for deadlock avoidance,
which checks whether a system is in a safe state or not before allocating resources to a process.

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 Banker's algorithm works based on the following:

 The system must know the maximum number of resources each process will need.

 The system must know the current allocation of resources to processes.

 The system must know the total number of resources available.

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.

3. Request: A process's demand for resources.

4. Allocation: The number of resources currently allocated to a process.

5. Available: The number of resources currently available in the system.

Steps to Implement the Banker's Algorithm for Deadlock Avoidance

1. Define Data Structures for Resources:

We will define data structures for keeping track of:

 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

int available[MAX_RESOURCES]; // Available resources

int allocation[MAX_PROCESSES][MAX_RESOURCES]; // Allocation matrix

int maximum[MAX_PROCESSES][MAX_RESOURCES]; // Maximum matrix

int need[MAX_PROCESSES][MAX_RESOURCES]; // Need matrix

// Function prototypes

void calculateNeed();

bool isSafeState();

bool checkRequest(int process, int request[]);

void resourceRequest(int process, int request[]);

void printSystemState();

2. Initialize the System Resources:

To simulate the system, we will initialize the total resources, allocated resources, and maximum
resources required by each process.

void initializeSystem() {

// Initialize available resources (total - allocated)

available[0] = 3; // 3 instances of Resource 1

available[1] = 3; // 3 instances of Resource 2

available[2] = 2; // 2 instances of Resource 3

// Allocation matrix

allocation[0][0] = 0; allocation[0][1] = 1; allocation[0][2] = 0;

allocation[1][0] = 2; allocation[1][1] = 0; allocation[1][2] = 0;

allocation[2][0] = 3; allocation[2][1] = 0; allocation[2][2] = 2;


allocation[3][0] = 2; allocation[3][1] = 1; allocation[3][2] = 1;

allocation[4][0] = 0; allocation[4][1] = 0; allocation[4][2] = 2;

// Maximum matrix

maximum[0][0] = 7; maximum[0][1] = 5; maximum[0][2] = 3;

maximum[1][0] = 3; maximum[1][1] = 2; maximum[1][2] = 2;

maximum[2][0] = 9; maximum[2][1] = 0; maximum[2][2] = 2;

maximum[3][0] = 4; maximum[3][1] = 2; maximum[3][2] = 2;

maximum[4][0] = 5; maximum[4][1] = 3; maximum[4][2] = 3;

// Calculate need matrix (maximum - allocation)

calculateNeed();

3. Calculate Need Matrix:

The Need matrix represents the remaining resource needs of each process to finish its execution.

void calculateNeed() {

for (int i = 0; i < MAX_PROCESSES; i++) {

for (int j = 0; j < MAX_RESOURCES; j++) {

need[i][j] = maximum[i][j] - allocation[i][j];

4. Check Safe State:

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() {

int work[MAX_RESOURCES]; // Work vector

bool finish[MAX_PROCESSES]; // Finish vector to track process completion

// Initialize work to available resources and finish to false

for (int i = 0; i < MAX_RESOURCES; i++) {


work[i] = available[i];

for (int i = 0; i < MAX_PROCESSES; i++) {

finish[i] = false;

int count = 0; // Count of processes that can finish

while (count < MAX_PROCESSES) {

bool progress = false;

for (int i = 0; i < MAX_PROCESSES; i++) {

if (!finish[i]) {

// Check if the process can finish

bool canFinish = true;

for (int j = 0; j < MAX_RESOURCES; j++) {

if (need[i][j] > work[j]) {

canFinish = false;

break;

// If process can finish, update work and finish

if (canFinish) {

for (int j = 0; j < MAX_RESOURCES; j++) {

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.

bool checkRequest(int process, int request[]) {

// Check if the request is less than or equal to the need

for (int i = 0; i < MAX_RESOURCES; i++) {

if (request[i] > need[process][i]) {

return false;

// Check if the request is less than or equal to the available resources

for (int i = 0; i < MAX_RESOURCES; i++) {

if (request[i] > available[i]) {

return false;

return true;

}
void resourceRequest(int process, int request[]) {

// Check if the request is valid

if (checkRequest(process, request)) {

// Pretend to allocate resources

for (int i = 0; i < MAX_RESOURCES; i++) {

available[i] -= request[i];

allocation[process][i] += request[i];

need[process][i] -= request[i];

// Check if the system remains in a safe state

if (isSafeState()) {

printf("Resource request granted.\n");

} else {

// Rollback the changes if the system is unsafe

for (int i = 0; i < MAX_RESOURCES; i++) {

available[i] += request[i];

allocation[process][i] -= request[i];

need[process][i] += request[i];

printf("Resource request denied due to unsafe state.\n");

} else {

printf("Invalid resource request.\n");

6. Print System State:

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("Resource %d: %d\n", i + 1, available[i]);

printf("\nAllocation Matrix:\n");

for (int i = 0; i < MAX_PROCESSES; i++) {

printf("Process %d: ", i);

for (int j = 0; j < MAX_RESOURCES; j++) {

printf("%d ", allocation[i][j]);

printf("\n");

printf("\nNeed Matrix:\n");

for (int i = 0; i < MAX_PROCESSES; i++) {

printf("Process %d: ", i);

for (int j = 0; j < MAX_RESOURCES; j++) {

printf("%d ", need[i][j]);

printf("\n");

Main Function

int main() {

initializeSystem();

// Print the initial state of the system

printSystemState();

// Simulate resource request for Process 1


int request1[] = {1, 0, 2}; // Process 1 requests 1 unit of Resource 1, 0 of Resource 2, and 2 of
Resource 3

resourceRequest(1, request1);

// Print the system state after the request

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 request granted.


Available Resources:

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.

You might also like