OS Lab Handout-Merged
OS Lab Handout-Merged
Spring 2024
Linux Vs Windows:
Windows is widely used operating system while Linux has its own advantages. Following are the
advantages discussed in the table below.
LINUX WINDOWS
Linux is an open source operating system i.e. Windows OS is a commercial operating system
user can change source code as per requirement and its closed source i.e. its source code is
inaccessible.
Linux has Monolithic kernel i.e. Whole operating Windows has a hybrid kernel i.e. Combination of
system works in the kernel space. microkernel and monolithic kernel.
File names are case-sensitive in Linux. File names are not case-sensitive in Windows.
Booting can be done from any disk. Booting can only be done from the prime disk.
Linux is highly reliable and secure. It has a Windows is less reliable than Linux. Over the
deeprooted emphasis on process management, recent years, Windows reliability has been
system security, and uptime. improved a lot. However, it still has some system
instabilities and security weaknesses because of
its oversimplified design.
Linux Components:
Major components of Linux are:
• Kernel
• System user space
• Applications Kernel:
Kernel is the base component of the OS. Without it, the OS doesn’t work. The kernel manages the
system’s resources and communicates with the hardware. It’s responsible for memory, process, and
file management.
System user space is the administrative layer for system-level tasks like configuration and software
installation. This includes the shell or command line, processes that run in the background, and the
desktop environment.
A type of software that lets you perform a task. Applications include everything from desktop tools and
programming languages to multiuser business suites. Most Linux distributions offer a central database
to search for and download additional apps.
Linux Shell:
Shell is a program that receives commands from the user and gives it to the OS to process, and it
shows the output. Shell is command line interface (CLI), a console that interacts with the system via
texts and processes. It’s similar to the Command Prompt application in Windows.
Linux Command:
A Linux command is a program or utility that runs on shell. Linux commands are executed on Terminal
by pressing ‘Enter’ at the end of the line. User can run commands to perform various tasks, from
package installation to user management and file manipulation.
A command may contain an option or a parameter. In some cases, it can still run without them. These
are the three most common parts of a command:
NOTE: All Linux commands are case sensitive i.e. ‘cp’ is not equivalent to ‘CP’. Also, all the files and
directories in linux are case sensitive so for example ‘/etc/hosts’ is not equivalent to ‘/etc/Hosts’ and so
hosts and Hosts are two different files in the same directory. When executing multiple commands in a
single line, use ; to separate them.
1. man
2. clear
3. exit
4. history
5. echo
6. alias, unalias
7. |
8. &&
1. man command
The man command provides a user manual of any commands or utilities you can run in Terminal,
including the name, description, and options.
man man[command_name]
For example, you want to access the manual for the ls command:
man ls
Enter this command if you want to specify the displayed section: man
man man 2 ls
3. exit command
4. history command
With history, the system will list up to 500 previously executed commands, allowing you to reuse
them without re-entering. Keep in mind that only users with sudo privileges can execute this
command. How this utility runs also depends on which Linux shell you use. To run it, enter the
command below:
history [option]
5. echo command
The echo command is a built-in utility that displays a line of text or string using the standard output.
Here’s the basic syntax: echo
[option] [string]
For example, you can display the text Hostinger Tutorials by entering:
-E displays the default option and disables the interpretation of backslash escapes.
6. alias, unalias commands alias allows you to create a shortcut with the same
When executed, it instructs the shell to replace one string with another.
alias Name=String
For example, you want to make e the alias for the exit command:
alias e=exit
unalias [alias_name]
7. |
If a user in Linux likes to combine two or more commands, pipes is the option. Pipe is
represented by the symbol ‘|’
8. &&
And command && is used to only allow the next command to run if the previous one is successful.
1. date
2. shutdown, poweroff , reboot
3. ps
4. kill
5. df
1. date command
The date command will display the system date.
3. ps command
The process status or ps command produces a snapshot of all running processes in your system. The
static results are taken from the virtual files in the /proc file system.
Executing the ps command without an option or argument will list the running processes in the shell
along with:
can use:
4. kill command
Use the kill command to terminate an unresponsive program manually. It will signal misbehaving
applications and instruct them to close their processes.
ps ux
After knowing what signal to use and the program’s PID, enter the following syntax:
There are 64 signals that you can use, but these two are among the most commonly used:
SIGTERM requests a program to stop running and gives it some time to save all of its progress.
The system will use this by default if you don’t specify the signal when entering the kill
command.
SIGKILL forces programs to stop, and you will lose unsaved progress.
For example, the program’s PID is 63773, and you want to force it to stop:
df command
Use the df command to report the system’s disk space usage, shown in percentage and kilobyte (KB).
Here’s the general syntax:
df [options] [file]
For example, enter the following command if you want to see the current directory’s system disk space
usage in a human-readable format:
df -h
If you want to check how much space a file or a directory takes up, use the du command. You can run
this command to identify which part of the system uses the storage excessively.
Remember, you must specify the directory path when using the du command. For example, to check
/home/user/Documents enter: du /home/user/Documents
Adding a flag to the du command will modify the operation, such as:
-h informs the last modification date of the displayed folders and files.
7. top command
The top command in Linux Terminal will display all the running processes and a dynamic real-time view
of the current system. It sums up the resource utilization, from CPU to memory usage.
The top command can also help you identify and terminate a process that may use too many system
resources.
8. htop command
The htop command is an interactive program that monitors system resources and server processes in
real time. It is available on most Linux distributions, and you can install it using the default package
manager.
Compared to the top command, htop has many improvements and additional features, such as mouse
operation and visual indicators. To use it, run the following command:
htop [options]
The uname or unix name command will print detailed information about your Linux system and
hardware. This includes the machine name, operating system, and kernel. To run this command,
simply enter uname into your CLI.
uname [option]
sudo command
Short for superuser do, sudo is one of the most popular basic Linux commands that lets you perform
tasks that require administrative or root permissions.
When using sudo, the system will prompt users to authenticate themselves with a password. Then, the
Linux system will log a timestamp as a tracker. By default, every root user can run sudo commands for
15 minutes/session.
If you try to run sudo in the command line without authenticating yourself, the system will log the
activity as a security event.
sudo (command)
ping
2. wget
3. hostname
4. ip
1. ping command
The ping command is one of the most used basic Linux commands for checking whether a network or
a server is reachable. In addition, it is used to troubleshoot various connectivity issues.
For example, you want to know whether you can connect to Google and measure its response time:
ping google.com
2. wget command
The Linux command line lets you download files from the internet using the wget command. It works in
the background without hindering other running processes.
The wget command retrieves files using HTTP, HTTPS, and FTP protocols. It can perform recursive
downloads, which transfer website parts by following directory structures and links, creating local
versions of the web pages.
For example, enter the following command to download the latest version of WordPress:
wget https://wordpress.org/latest.zip
3. hostname command
Run the hostname command to know the system’s hostname. You can execute it with or without
an option. Here’s the general syntax:
hostname [option]
For example, enter the following command to know your computer’s IP address:
hostname –i
4. ip command
The ip command is a Linux net-tool for system and network administrators. IP stands for Internet
Protocol and as the name suggests, the tool is used for configuring network interfaces.
Older Linux distributions used the ifconfig command, which operates similarly. However, ifconfig has a
limited range of capabilities compared to the ip command.
OBJECTS (or subcommands) that you will use most often include:
2. address (addr/a) – used to display and modify protocol addresses (IP, IPv6).
4. neigh (n) – used to display and manipulate neighbor objects (ARP table).
➢ pwd command
Use the pwd command to find the path of your current working directory. Simply entering pwd will
return the full current path – a path of all the directories that starts with a forward slash (/). For example,
/home/username.
[option]
➢ cd command
To navigate through the Linux files and directories, use the cd command. Depending on your current
working directory, it requires either the full path or the directory name.
Running this command without an option will take you to the home folder. Keep in mind that only users
with sudo privileges can execute it.
cd Photos
If you want to switch to a completely new directory, for example, /home/username/Movies, you have to
enter cd followed by the directory’s absolute path: cd /home/username/Movies
previous directory.
➢ ls command
The ls command lists files and directories within a system. Running it without a flag or parameter will
show the current working directory’s content
To see other directories’ content, type ls followed by the desired path. For example, to view files in the
Documents folder, enter:
ls /home/username/Documents
Here are some options you can use with the ls command:
ls -lh shows the file sizes in easily readable formats, such as MB, GB, and TB.
➢ mkdir command
mkdir Music
To make a new directory called Songs inside Music, use this command:
mkdir Music/Songs
-p or –parents create a directory between two existing folders. For example, mkdir -p
Music/2020/Songs will make the new “2020” directory.
-m sets the file permissions. For instance, to create a directory with full read, write, and execute
permissions for all users, enter mkdir -m777 directory_name.
➢ rmdir command
To permanently delete an empty directory, use the rmdir command. Remember that the user running
this command should have sudo privileges in the parent directory.
For example, you want to remove an empty subdirectory named personal1 and its main folder mydir:
rmdir -p mydir/personal1
➢ cp command
Use the cp command to copy files or directories and their content. Take a look at the following use
cases.
To copy one file from the current directory to another, enter cp followed by the file name and the
destination directory. For example:
cp filename.txt /home/username/Documents
To copy the content of a file to a new file in the same directory, enter cp followed by the source file and
the destination file:
cp filename1.txt filename2.txt
To copy an entire directory, pass the -R flag before typing the source directory, followed by the
destination directory:
cp -R /home/username/Documents /home/username/Documents_backup
➢ mv command
The primary use of the mv command is to move and rename files and directories. Additionally, it
doesn’t produce an output upon execution.
Simply type mv followed by the filename and the destination directory. For example, you want to move
filename.txt to the /home/username/Documents directory: mv filename.txt
/home/username/Documents. You can also use the mv command to rename a file:
mv old_filename.txt new_filename.txt
➢ rm command
The rm command is used to delete files within a directory. Make sure that the user performing this
command has write permissions.
Remember the directory’s location as this will remove the file(s) and you can’t undo it.
rm filename
➢ touch command
The touch command allows you to create an empty file or generate and modify a timestamp in the
Linux command line.
For example, enter the following command to create an HTML file named Web in the Documents
directory:
touch /home/username/Documents/Web.html
➢ cat command
Concatenate, or cat, is one of the most frequently used Linux commands. It lists, combines, and writes
file content to the standard output. To run the cat command, type cat followed by the file name and its
extension. For instance: cat filename.txt.
cat filename1.txt filename2.txt > filename3.txt merges filename1.txt and filename2.txt and stores the
output in filename3.txt.
Linux allows users to edit and manage files via a text editor, such as nano, vi, or jed. nano and vi come
with the operating system, while jed has to be installed.
The nano command denotes keywords and can work with most languages. To use it, enter the
following command: nano [filename] vi uses two operating modes to work – insert and command.
insert is used to edit and create a text file. On the other hand, the command performs operations, such
as saving, opening, copying, and pasting a file.
vi [filename]
jed has a drop-down menu interface that allows users to perform actions without entering keyboard
combinations or commands. Like vi, it has modes to load modules or plugins to write specific texts.
➢ locate command
Moreover, adding the -i argument will turn off case sensitivity, so you can search for a file even if you
don’t remember its exact name.
To look for content that contains two or more words, use an asterisk (*). For example:
locate -i school*not
The command will search for files that contain the words school and note, whether they use uppercase
or lowercase letters.
➢ find command
Use the find command to search for files within a specific directory and perform subsequent operations.
Here’s the general syntax:
For example, you want to look for a file called notes.txt within the home directory and its subfolders:
➢ grep command
Another basic Linux command on the list is grep or global regular expression print. It lets you find a
word by searching through all the texts in a specific file.
Once the grep command finds a match, it prints all lines that contain the specific pattern. This
command helps filter through large log files.
For example, you want to search for the word blue in the notepad.txt file:
➢ head command
The head command allows you to view the first ten lines of a text. Adding an option lets you change the
number of lines shown. The head command is also used to output piped data to the CLI.
For instance, you want to view the first ten lines of note.txt, located in the current directory:
head note.txt
-n or –lines prints the first customized number of lines. For example, enter head -n 5 filename.txt to
show the first five lines of filename.txt.
➢ tail command
The tail command displays the last ten lines of a file. It allows users to check whether a file has new
data or to read error messages.
For example, you want to show the last ten lines of the colors.txt file:
tail -n colors.txt
➢ cat command
Concatenate, or cat, is one of the most frequently used Linux commands. It lists, combines, and writes
file content to the standard output. To run the cat command, type cat followed by the file name and its
extension. For instance: cat filename.txt.
cat filename1.txt filename2.txt > filename3.txt merges filename1.txt and filename2.txt and stores the
output in filename3.txt.
➢ chmod command
chmod is a common command that modifies a file or directory’s read, write, and execute permissions.
In Linux, each file is associated with three user classes – owner, group member, and others.
For example, the owner is currently the only one with full permissions to change note.txt. To allow
group members and others to read, write, and execute the file, change it to the -rwxrwxrwx permission
type, whose numeric value is 777:
➢ chown command
The chown command lets you change the ownership of a file, directory, or symbolic link to a specified username.
You can create C files with the same method as any other file creation.
Nano test.c (Here I am using the nano editor although you can use any editor of your choice i.e.
gedit)
Now write some C-Code in the file as an example I am writing a simple Hello World line in it.
Normally in a OS environment you would have an editor that would do the compilation of the code
automatically but since we are using the terminal mainly, we would have to compile it ourselves. There are two
popular ways to compile the above file.
gcc test.c
GCC is the GNU compiler collection which contains multiple compilers ranging from C to C++, Objective -C,
Fortran, Ada, Go and D as well as the libraries for these programming languages. The above command will read
the code and compile the code into an output file know as a.out.
The a.out is the output file which contains the output of the C-code that is compiled. Note if your code has I/O dependencies
such as taking input from the user or writing to the file, It will not be completed until the output file is executed.
But having multiple C/C++ files with the same a.out will be a problem as the OS will keep overwriting the contents of the output
file to the new file that it just compiled. To get around this we can rename this output file via the following command.
Here you can see we compiled the output file to a new file which we named as output_file. Notice it has no extension (like we
say .out with the old output file). That’s because the operating system interprets it as an executable and it does not require an
extension to be mentioned with the file. In GUI based Linux distribution this would be labelled with a green text to signify that
this file is an executable file. The -o is a flag to forward the output to the file we want to create.
Objectives:
Lab Tasks:
EXPERIMENT 1
Introduction to OS and LINUX
OBJECTIVE:
• To get familiarized with the basics of operating systems
• Learn the basic commands used in Linux
BACKGROUND:
On Computer Startup:
Operating System:
• What is Operating System?
Supports computer’s basic functions as shown in Figure 1.1
• What tasks an OS Perform?
▪ Processor management
▪ Memory management
▪ Device management
▪ Storage management
▪ Application interface
▪ User interface
• Types
▪ Linux
▪ Windows 8, Windows 7, Vista, XP
▪ Mac
OS Basic Functions
Figure 1.1
Page 2 of 8
lOMoAR cPSD| 36312306
What is LINUX?
• A fully-networked 32/64-Bit Unix-like Operating System
▪ Compilers Like C, C++
• Multi-user, Multitasking
• Coexists with other Operating Systems
• Includes the Source Code
• Open Source
Why is it Significant?
• Growing popularity
• Powerful
▪ Runs on multiple hardware platforms
▪ Users like its speed and stability
▪ No requirement for latest hardware
▪ It is free
▪ Licensed under GPL (General Public License)
System Structure:
An operating system is a construct that allows the user application programs to interact with
the system hardware. This is further divided in two layers i.e Kernel and Shell. Kernel deals
with the Hardware and Shell deals with Applications as shown in Figure 1.2.
Applications
Shell
Kernel
Hardware
Page 3 of 8
lOMoAR cPSD| 36312306
• To execute a command, type its name and arguments at the command line
• <command_name> <space> <options> <space> <arguments>
Editors:
Several Choices available:
• vi Standard UNIX editor
• the XEDIT like editor
• xedit X windows text editor
• emacs Extensible, Customizable Self-Documenting Display Editor
• pico Simple display-oriented text editor
• nedit X windows Motif text editor
Page 4 of 8
lOMoAR cPSD| 36312306
Windows LINUX
• The directories in MS-DOS path are • Paths are separated by ‘/’.
separated by ‘\’ • File names are case sensitive.
• File names are case insensitive. • There is only a single hierarchal
• Where DOS/Windows had various directory structure (resembles a tree).
partitions and then directories under Everything starts from the root
those partitions. directory, represented by '/', and then
• An executable is one with an extension • expands into sub-directories.
of .exe, .com or .bat. • Any file whose execute permission is
• You can set attributes to make file read turned on is executable
only, hidden • You can set permissions on a file
Page 5 of 8
lOMoAR cPSD| 36312306
Virtual Machine:
Command Description
Command Description
pwd Display the current working directory.
ls List files and directories.
cd Desktop Change the current directory to Desktop.
mkdir NewFolder Create a new directory named "NewFolder".
rmdir NewFolder Remove the empty directory "NewFolder".
cp file.txt /tmp Copy "file.txt" to the "/tmp" directory.
mv file.txt newname.txt Rename "file.txt" to "newname.txt".
rm oldfile.txt Remove the file "oldfile.txt".
touch newfile.txt Create an empty file named "newfile.txt".
nano myfile.txt Open the nano text editor for editing.
cat myfile.txt Display the content of "myfile.txt".
echo "Hello, Linux!" Display the message "Hello, Linux!".
man ls Display the manual page for ls.
chmod 755 script.sh Change the permissions of "script.sh".
chown user:group myfile.txt Change the owner and group of "myfile.txt".
ps aux Display information about active processes.
kill 1234 Terminate the process with PID 1234.
top Display real-time system statistics.
df -h Display disk space usage.
du -h Display file and directory space usage.
grep "pattern" file.txt Search for a pattern in "file.txt".
find /home/user -name Search for ".txt" files in /home/user.
"*.txt"
ps aux Display information about active processes.
grep "pattern" file.txt Search for a pattern in "file.txt".
grep -c "pattern" file.txt Display the count of occurrences of the pattern in
"file.txt".
sudo apt install gcc Installs the GNU Compiler Collection (GCC).
sudo apt install g++ Installs the GNU C++ Compiler (g++).
gcc --version Displays the installed version of GCC.
g++ --version Displays the installed version of g++.
Page 6 of 8
lOMoAR cPSD| 36312306
Q3: In a Linux terminal, using a single echo command, print the following output:
“Welcome to Linux, Linux is free, secure and open source”.
Q1: In the Linux terminal, perform the following tasks using appropriate commands:
Q2: Open a terminal on your Ubuntu system and perform the following tasks:
• Create a directory named 'c_programs' in the 'Documents' directory using the mkdir command.
• Move into the 'c_programs' directory using the cd command.
• Install the GNU Compiler Collection (gcc) if not already installed using the appropriate
package manager command (e.g., sudo apt install gcc).
• Create an empty text file named 'hello.c' in the 'c_programs' directory using the touch
command.
• Verify the existence of the newly created 'hello.c' file using the ls command.
• Use a text editor (e.g., nano or gedit) to add the C code to 'hello.c':
• Compile 'hello.c' using the gcc command and create an executable named 'output' using the -o
flag
Page 7 of 8
lOMoAR cPSD| 36312306
• Identify the command to list files in the current directory that have names starting with an
uppercase letter.
• Create three new directories named "Reports," "Projects," and "Archive" using a single
command if they don't already exist.
• Copy files in the current directory containing the character string "report" into the "Reports"
subdirectory.
• Copy files in the "Reports" subdirectory with names ending in ".txt" or ".docx" into the
"Projects" subdirectory.
• Copy files in the "Projects" subdirectory containing the character strings "notes" or "misc" into
the "Archive" subdirectory.
• Copy files starting with "important_" from the "Archive" subdirectory into the "Backup"
subdirectory. Move files starting with "obsolete_" from the "Archive" subdirectory into the
"Backup" subdirectory.
• Delete all files containing the sequence "obsolete" from the "Backup" subdirectory.
• Create a new user named "secureuser" with the password set as "secure123" using the
appropriate command.
• Use the terminal to display the home directories of all users.
• Modify the password of "secureuser" to "newpass2024" using the necessary command.
• Access the system using the credentials of the "secureuser."
• Utilize the terminal to initiate a system restart, and subsequently, remove the "secureuser"
along with their associated home directory.
Page 8 of 8
CL2006 - Operating Systems Fall 2024
LAB # 2 MANUAL (Common)
Please note that all labs topics including pre-lab, in-lab and post-lab exercises are part of the theory and lab
syllabus. These topics will be part of your Midterms and Final Exams of lab and theory.
Objectives:
Lab Tasks:
3. Compiler Process:
a. Stages in the compiler process: Compiler Stage, Assembler Stage, Linker Stage.
b. Compilation from C++ language code to Assembly language to object code.
c. Linking object code to code libraries to produce the executable program.
4. Makefiles:
a. Purpose of Makefiles: Separate compilation, describe project file dependencies.
b. Overview of the make utility.
c. Introduction to rules in makefiles, Example makefile structure with a rule.
d. Rule elements: Target, Dependencies, and Commands.
e. Automatic variables ($@, $<, $^, $?) and their role in rules.
f. Common Example
Created by: Hamza Yousuf. Date: January, 2019. Modified by: Nadeem Kafi (27/01/2024)
DEPARTMENT OF ELECTRICAL ENGINEERING, FAST-NU, LAHORE
lOM oAR c P S D | 3631 230 6
Lab # 2 Manual
EXPERIMENT 2
Creating, Compiling and Executing C/C++ programs using gcc/g++Compilers and
Make File
OBJECTIVE:
• Learn the use of g++ and gcc compilers to compile and execute C++ and C programs
• To get familiarized with the working of Make File for C/C++ programs
BACKGROUND:
For C:
Command: gcc source_files… -o output_file
Source files need not be cpp or c files. They can be preprocessed files, assembly files, or object files.
The whole compilation file works in the following way:
Cpp/C file(s) → Preprocessed file(s) → Assembly File(s) Generation → Object file(s) Generation → Final Executable
Every c/cpp file has its own preprocessed file, assembly file, and object file.
A file generated using any option can be used to create the final executable. For example, let’s
suppose that we have two source files: math.cpp and main.cpp, and we create objectfiles:
The object files created using above two commands can be used to generate the final executable.
The file named “my_executable” is the final exe file. There is specific extension for
executable files in Linux.
Command line arguments are a way to pass data to the program. Command line arguments are passed to
the main function. Suppose we want to pass two integer numbers to main function of an executable
program called a.out. On the terminal write the following line:
./a.out 1 22
./a.out is the usual method of running an executable via the terminal. Here 1 and 22 are the numbers that
we have passed as command line argument to the program. These arguments are passed to the main
function.
Page 2 of 8
lOM oAR c P S D | 3631 230 6
Lab # 2 Manual
In order for the main function to be able to accept the arguments, we have to change the signature of
main function as follows:
• argc is the counter. It tells how many arguments have been passed.
• arg is the character pointer to our arguments.
argc in this case will not be equal to 2, but it will be equal to 3. This is because the name
./a.out is also passed as command line argument. At index 0 of arg, we have ./a.out; at index 1, we have
1; and at index 2, we have 22. Here 1 and 22 are in the form of character string, we have to convert
them to integers by using a function atoi. Suppose we want to add the passed numbers and print the sum
on the screen:
Compiler Process:
➢ Compiler Stage: All C++ language code in the .cpp file is converted into a lower-levellanguage
called Assembly language; making .s files.
➢ Assembler Stage: The assembly language code made by the previous stage is thenconverted
into object code which are fragments of code which the computer understands directly. An
object code file ends with .o.
➢ Linker Stage: The final stage in compiling a program involves linking the object codeto code
libraries which contain certain "built-in" functions, such as cout. This stage produces an
executable program, which is named a.out by default.
Makefiles:
Naming:
Running make:
$make
or
$make –f filename
Where filename is the name of your file is not “makefile” or “Makefile”
Automatic variables:
Automatic variables are used to refer to specific part of rule components.eval.o : eval.c eval.h
g++ -c eval.c
$@ - The name of the target of the rule (eval.o).
$< - The name of the first dependency (eval.c).
$^ - The names of all the dependencies (eval.c eval.h).
$? - The names of all dependencies that are newer than the target make
Page 3 of 8
lOM oAR c P S D | 3631 230 6
Lab # 2 Manual
Normally, you would compile this collection of knows that the rule hellomake needs to be executed if
code by executing the following command: any of those files change. Immediately, you have solved
problem #1 and can avoid using the up arrow
gcc -o hellomake hellomake.c repeatedly, looking for your last compile command.
hellofunc.c -I However, the system is still not being efficient in terms
of compiling only the latest changes.
This compiles the two .c files and names the executable
hellomake. The -I is included so that gccwill look in the One very important thing to note is that there is a tab
current directory (.) for the include file hellomake.h. before the gcc command in the makefile. There must be
a tab at the beginning of any command, and make will
Without a makefile, the typical approach to the not be happy if it's not there.
test/modify/debug cycle is to use the up arrow in a
terminal to go back to your last compile command so In order to be a bit more efficient, let's try the
you don't have to type it each time, especially once following:
you've added a few more .c files to the mix.
Makefile 2
Unfortunately, this approach to compilation has two
downfalls. First, if you lose the compile command or CC=gcc
switch computers then you have to retype it from CFLAGS=I
scratch, which is inefficient at best. Second, if you are
hellomake: hellomake.o hellofunc.o
only making changes to one .c file, recompiling all of $(CC) -o hellomake hellomake.o
them every time is also time-consuming and hellofunc.o
inefficient. So, it's time to see what we can do with a
makefile. So now we've defined some constants CC and
CFLAGS. It turns out these are special constants that
The simplest makefile you could create would look communicate to make how we want to compile the files
something like: hellomake.c and hellofunc.c. In particular, the macro
CC is the C compiler to use, and CFLAGS is the list of
Makefile 1 flags to pass to the compilation command. By putting
the object files--hellomake.o and hellofunc.o--in the
hellomake: hellomake.c hellofunc.c
dependency list and in the rule, make knows it must
gcc -o hellomake hellomake.c
hellofunc.c -I first compile the .c versions individually, and then build
the executable hellomake.
If you put this rule into a file called Makefile or
makefile and then type make on the command line. It Using this form of makefile is sufficient for most
will execute the compile command as you have written small-scale projects. However, there is one missing:
it in the makefile. Note that make with no arguments dependency on the include files. If you were to
executes the first rule in the file. make a change to hellomake.h, for example, make
would not recompile the .c files, even though they
Furthermore, by putting the list of files on which the needed to be. In order to fix this, we need to tell
command depends on the first line after the : make makethat all .c files depend on certain .h files. We
Page 4 of 8
lOM oAR c P S D | 3631 230 6
Lab # 2 Manual
can do this by writing a simple rule and adding it to file(s) that the source files depend on.
the makefile. OBJ = hellomake.o hellofunc.o:
This line defines a variable `OBJ` and sets its value to
Makefile 3 `hellomake.o hellofunc.o`. `OBJ` typically stands for object
files, and it lists the object files that need to be generated by
CC=gcc compiling the corresponding source files.
CFLAGS=I. `%.o: %.c $(DEPS)`:
DEPS = hellomake.h This is a pattern rule that specifies how to generate an
object file (`%.o`) from a corresponding source file (`%.c`)
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
along with its dependencies (`$(DEPS)`). When invoked,
this rule tells `make` that for any `.o` file it needs to create,
hellomake: hellomake.o hellofunc.o it can find the corresponding `.c` file and its dependencies
$(CC) -o hellomake hellomake.o in order to compile them.
hellofunc.o `$(CC) -c -o $@ $< $(CFLAGS)`:
• This line is the recipe associated with the pattern rule
This addition first creates the macro DEPS, which isthe defined above. It specifies the commands to compile a
set of .h files on which the .c files depend. Then we define `.c` file into an object file.
a rule that applies to all files ending in the • `$(CC)`: Evaluates to `gcc`, indicating the compiler to
.o suffix. The rule says that the .o file depends uponthe .c be used.
version of the file and the .h files included in the DEPS • `-c`: Instructs the compiler to generate an object file.
macro. The rule then says that to generatethe .o file, make • `-o $@`: Specifies the output file name, where `$@` is
needs to compile the .c file using the compiler defined in a built-in variable representing the target of the rule,
the CC macro. The -c flag says to generate the object file, which in this case is the object file being generated.
the -o $@ says to put the output of the compilation in the • `$<`: Represents the first prerequisite of the rule, which
file named on the left side of the :, the $< is the first item is the source file (`%.c`).
in thedependencies list, and the CFLAGS macro is • `$(CFLAGS)`: Contains additional compiler flags,
defined as above. though it's incomplete in this Makefile.
`hellomake: $(OBJ)`:
As a final simplification, let's use the special macros $@ This line defines a target `hellomake` that depends on the
and $^, which are the left and right sides of the:, object files listed in `$(OBJ)`. It specifies that the
respectively, to make the overall compilation rulemore executable `hellomake` should be built using these object
general. In the example below, all of the include files files.
should be listed as part of the macro DEPS, and all of the
object files should be listed aspart of the macro OBJ. `$(CC) -o $@ $^ $(CFLAGS)`:
• This line is the recipe associated with the target
Makefile 4 `hellomake`. It specifies the commands to link the
object files into an executable.
CC=gcc
CFLAGS=-I • `$(CC)`: Evaluates to `gcc`, indicating the linker to be
DEPS = hellomake.h used.
OBJ = hellomake.o hellofunc.o • `-o $@`: Specifies the output file name, where `$@` is
a built-in variable representing the target of the rule,
%.o: %.c $(DEPS) which in this case is the executable being generated
$(CC) -c -o $@ $< $(CFLAGS) (`hellomake`).
• `$^`: Represents all the prerequisites of the rule
hellomake: $(OBJ)
(`$(OBJ)`), i.e., the object files.
$(CC) -o $@ $^ $(CFLAGS)
• `$(CFLAGS)`: Contains additional linker flags, though
it's incomplete in this Makefile.
Let's break down each line:
CC=gcc: This line defines a variable `CC` and sets its value
to `gcc`, indicating that the GNU C Compiler (`gcc`) will
be used for compiling the source files.
CFLAGS=-I: This line defines a variable `CFLAGS` and
sets its value to `-I`. `-I` is a compiler option used to
specify additional directories to search for header files.
However, it seems incomplete here as no directory is
specified after `-I`.
DEPS = hellomake.h: This line defines a variable `DEPS`
and sets its value to `hellomake.h`. `DEPS` typically stands
for dependencies, and in this case, it specifies the header
Page 5 of 8
lOM oAR c P S D | 3631 230 6
Lab # 2 Manual
SYSTEM_TRUSTED_KEYS
Recompiling the Linux kernel $ scripts/config --disable
SYSTEM_REVOCATION_KEYS
$ scripts/config --set-str
The general steps to recompile the Ubuntu kernel CONFIG_SYSTEM_TRUSTED_KEYS ""
from sources with parameter changes: $ scripts/config --set-str
$uname –r CONFIG_SYSTEM_REVOCATION_KEYS ""
Installing dependencies
- Install necessary build tools and dependencies. If Compile Kernel:
you have not built a kernel on your system before, - Build the kernel and modules:
there are some packages needed before you can $make -j$(nproc)
successfully build. You can get these installed with:
$sudo apt install build-essential - The `-j$(nproc)` option enables parallel
libncurses-dev bison flex libssl-dev compilation, utilizing the number of available
libelf-dev fakeroot
processor cores. Press Enter repeatedly to confirm
$sudo apt install dwarves thedefault options for the generation of new
certificates.
The above are for Ubuntu 20.04.
Install Modules:
Download Kernel Sources - Install the kernel modules:
$sudo make modules_install
Next we need to need to download the kernel source
from the offical https://www.kernel.org/ website.
Install New Kernel:
Choose the latest longterm release and copy the link - Install the new kernel:
of the tarball hyperlink. Then use this link to $sudo make install
download and unpack the kernel source to your
Ubuntu machine: - This will update the bootloader configuration
$wget (GRUB) and copy the new kernel image to `/boot`.
https://cdn.kernel.org/pub/linux/kerne
l/v6.x/linux-6.1.73.tar.xz Update GRUB Configuration:
$tar -xf linux-6.1.73.tar.gz - Ensure that GRUB is aware of the new kernel. Run:
$ cd linux-6.1.73 $sudo update-grub
$ scripts/config --disable
Page 6 of 8
In Lab Questions:
Q1: Create a C program for a grade calculator. Accept command line parameters representing the scores of
students (out of 100) and calculate their average grade. Implement robust error checking for missing or incorrectly
formatted parameters. Execute the program with varying sets of student scores to observe the calculated average
grades.
Q2: Write a simple C program that accepts a series of integers as command line parameters, stores them in an
array, sorts the array in ascending order, and prints the sorted array?
Q3: Mini Event Reservation System
a) Create a header file named event_reservation.h that declares functions for an Event Reservation System. Declare
functions for adding, updating, and deleting events, as well as displaying events.
b) Implement the functions declared in the event_reservation.h header file in a source file named event.c. Provide
the necessary logic to add, update, and delete events within this file.
c) Develop another source file named event_detail_main.c that includes the main function. In the main function,
call the functions declared in event_reservation.h to showcase adding, updating, and deleting events.
d) Design a Makefile to facilitate the compilation and execution of the program. Define targets for building the
executable, cleaning the generated files, and running the program. Specify the compiler (CC := gcc) in the Makefile.
Organize the source code into directories (SRC_DIR, OBJ_DIR, BIN_DIR). Specify the target executable (TARGET :=
event_reservation). Ensure that the Makefile commands cover the compilation, execution, and cleaning aspects of
the program. After creating the files, utilize the Makefile commands to compile and run your mini event reservation
system.
POST Lab Question :
Q1: Modular Product Management System in C:
Part 1)
a) Product.header:
In the "Product.header" file, Include private attributes such as product ID, name, description, quantity,
price, and net price. Declare public member functions for adding, updating, and deleting products.
b) Product.c:
In "Product.c," implement the functions declared in "Product.header" for adding, updating, and deleting
products.
c) Vendor.header:
In the "Vendor.header" file, Include private attributes such as vendor ID, name, contact person, and contact
number. Declare public member functions for adding, updating, and deleting vendors.
d) Vendor.c:
In "Vendor.c," implement the the functions declared in "Vendor.header" for adding, updating, and deleting
vendors.
e) Stock.header:
In the "Stock.header" file, Include private attributes such as stock ID, product name, and available quantity.
Declare public member functions for adding, updating, and deleting stock entries.
f) Stock.c:
In "Stock.c," implement the functions declared in "Stock.header" for adding, updating, and deleting stock
entries.
h) main.c:
Additionally, create a simple main program in "main.c" that will Call the declared member functions to
demonstrate the functionalities of adding, updating, and deleting entities within the system.
2) Makefile:
Design a Makefile to facilitate the compilation and execution of a modular Product Management System
written in C. The Makefile should support three distinct methods to accommodate various build and
execution scenarios.
all:
Create a single target named "all" that compiles the source files (Product.c, Vendor.c, Stock.c, and main.c)
into object files and links them to generate the final executable named "main."
Implement multiple targets:
"build" to compile the source files into object files.
"execute" to run the resulting executable.
"clean" to remove the generated object files and the executable.
Explain the purpose of each target and provide the respective commands.
Individual Targets for Files Method:
Extend the Makefile with individual targets for each source file: "build_product," "build_vendor,"
"build_stock," and "build_main" to compile the corresponding source files into object files.
Corresponding "clean" targets ("clean_product," "clean_vendor," "clean_stock," and "clean_main") to
remove the associated object files.
Ensure that the Makefile defines the compiler (CC := gcc) and compiler flags (CFLAGS := -Wall -std=c99).
Organize the source code into directories (SRC_DIR, OBJ_DIR, BIN_DIR). Specify the target executable
(TARGET := main).
Q2: Design a C program for Linux System Monitoring. The program should take command line arguments to specify
the parameters to monitor, such as CPU usage, memory usage, and disk space. If no parameters are provided,
display an error message. Print the relevant system information on the console based on the specified parameters.
Q3: Develop a C program that acts as a time tracker. The program should accept command line parameters
representing start and end times in the format HH:MM:SS. Calculate and display the duration between the two
times. Implement robust error checking for missing or incorrectly formatted parameters. Execute the program with
different time intervals.
Q4: Create a C++ program that processes a series of floating-point numbers provided as command line parameters.
Store them in an array, calculate statistical measures (mean, median, standard deviation), and output the results to
a file. Handle error scenarios, such as missing or incorrect parameters, and execute the program with diverse input
series.
Q5: Design a C++ program for a Word Frequency Analyzer, comprising the following classes in separate files:
WordFrequencyCounter.h and WordFrequencyCounter.cpp. The program should accept a text file as a command
line argument, read its content, and count the frequency of each unique word. Create objects of the
WordFrequencyCounter class in the main function, populate them with data, and display the word frequencies.
Compile all classes using a Makefile to ensure modularity.
Solution of Lab 2 :
Part d:
# Makefile
CC := gcc
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
TARGET := event_reservation
# Source files(Please open lab 1 handout and read wildcard part first)
$(BIN_DIR)/$(TARGET): $(OBJ)
@mkdir -p $(BIN_DIR)
$(CC) -o $@ $^
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(OBJ_DIR)
clean:
run: $(BIN_DIR)/$(TARGET)
./$(BIN_DIR)/$(TARGET)
make run
This will compile the source files, generate the executable (event_reservation), and execute the
program, showcasing the mini event reservation system. Adjust the file paths and content as needed
for your specific implementation.
CL-2006 Operating LAB – 02 – Handout # 1
Systems Shell Scripting & vi, Aliases,
Environment Variables and Subshells
• Mr. Monis
• Mr. Taha Ahmed, and
• Mr. Shakir Hussain
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 1
Objective
The lab examines the use of shell scripts as a way to write programs that accomplish various forms of processing in a
Linux environment.
Shell Scripting
Shell script can be viewed as a high level program that is created with a simple text editor. Once created, a user may
execute a shell script by simply invoking the filename of the shell script. It is unnecessary to compile the shell script
first. Rather, each time the shell script is invoked, a shell interprets or compiles the shell script as it executes it.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 2
A shell script invokes commands that you can issue through a command-line. In addition, a shell script also allows for
more sophisticated processing, such as decision making and repetition for the work it invokes. In this manner, a shell
script can be written to accomplish a series of tasks more easily and quickly than if the user had to type the
commands for the tasks every time. Shell scripts are also a common way to schedule jobs to be automatically
invoked by the system at specific times.
To create a shell script file, create a new file with any name and with extension ‘.sh’. Note you can also create the
shell script file without the extension specified but then the file editor e.g. gedit’s content will no longer be content-
aware. The demonstration of creating the file is shown below:
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 3
To invoke a shell script simply type in your terminal: ‘./’ followed by the filename with the extension ‘.sh’. For
example, if I want to execute shell script having filename: ‘shelly.sh’ I would execute it as shown in the screenshot
below.
Make sure the file i.e. in my case ‘shelly.sh’ is executable. In case the file is not executable you need to add access
permission using ‘chmod’ command which we discussed in lab manual 02.
Notice the path when I invoke shell script. The first one is: ‘./Desktop/shelly.sh’ which specified that in folder Desktop
there is an executable filename ‘shelly.sh’ which it simply executed. Now when I tried ‘./shelly.sh’ it gave me the
error of no such file or directory because the parent directory of Desktop does not contain that file. After changing
directory to Desktop, I retried the command and it executed. Hence in invoking a shell script you need to specify the
path where the filename is. Otherwise the system won’t be able to find it and/or execute it.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 4
Variables
Like most other programming languages, a shell script can use variables to store data for future retrieval. The names
for shell script variable may consist of alphabetic letters, underscores, or digits (but not in the beginning). Letters are
case sensitive. There are two types of variables used in shell programming.
1. System Variables
2. User Defined Variables
System variables are created and maintained by Linux. These types of variables will be denoted in upper case letters.
To get the details of available system variables, issue the command $set. Users variables are defined by users. They
are usually defined in lower case letters.
To store a value in a variable within a shell script, specify the assignment as shown below.
X=1
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 5
y=100.25
message=’hellow world’
In the figure above, the value 1 is stored in x, the value 100.25 in y, and the string value ‘hello world’ in message.
When a variable appears initially in a script in an assignment statement, the script automatically declares the variable
with the appropriate data type to hold the assigned value.
To obtain the value stored in the variable, specify the $ symbol followed by the variable name. As shown below:
echo $message
newMessage=$message
echo “The message is: $newMessage”
In the example above, the first line shows how to write the value of the variable ‘message’ to the screen, the second
line, assigns the value of the variable ‘message’ to the variable ‘newMessage’ and lastly, the third line shows how to
write the value of a variable along with other text. Notice that the example uses double quotes to enclose the text
and variable name. You may omit the double quotes, but you cannot use single quotes. The use of single quotes in
this example will actually instruct echo to write the enclosed contents exactly as they appear.
Comments
A comment is a line or part of the line that not executed in any programming language. In shell script, a comment
starts with the # symbol and continues to the end of that line. This implies that a comment may either take an entire
line if # appears as the first character on any line in a shell script. Alternatively, it may appear on the same line with
some other action, after the action specification. The example below will make this paragraph more meaningful.
# I am a comment, I will not be executed echo ‘hellow from comment’; date; pwd #this line will be
executed till the # symbol appears
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 6
echo “this is first piece” “this is second piece” 123.45 echo “this is string”
$variable
To take input from the keyboard into a shell script variable, you can use the read command followed by the variable.
Examples below shows how a shell script can prompt the user for a value and read that value into a variable.
#utilizing read to print a prompt and read input into two variables read -p
“Enter your first name and last name: “ FirstName LastName echo -n “First
Name: $FirstName” “LastName: ” echo -n $LastName
Accessing Arguments
You can send arguments when you invoke a shell script, the arguments can be in any number. The shell store those
arguments passed in variable $n where n = {1,2,3…9} and you pass the arguments just like in any other command. The
below shell script and terminal shows the execution of a shell script which is using command line arguments.
“Argument 2: $2”
The screenshot below shows the execution of the above shell script.
Other arguments available in shell script and their usage/description is provided in the table below.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 7
S.NO Variable Description
1 $0 The filename of the current script.
These variables correspond to the arguments with which a script was invoked. Here
n is a positive decimal number corresponding to the position of an argument (the
2 $n
first argument is $1, the second argument is $2, and so on).
Arithmetic Operations
In shell script, you can perform arithmetic operations, in calculations or within the formula. You must enclose the
formula or calculation with a set of double parentheses (( )). There should be no space between the two right and left
parentheses. The example below shows how to use arithmetic operations.
Num=10
(( Double = 2 * $Num )) echo “Twice the number is
$Double” (( DoublePlus1 = 2 * $Num + 1 )) echo
“Twice the Number Plus 1 is $DoublePlus1”
(( DoubleQPlus1 = 2 * ($Num +1) )) echo “Twice the
number plus 1 is $DoubleQPlus1”
(( half = $Num/2 )) echo “Half
the number is $half”
Some arithmetic operators which are commonly used is given below in the table:
Conditional Statements
Shell script can use conditions and branches to specify under what circumstances one or more statements should
execute. One form of conditions with branches involves if statement structure. A decision structure requires one or
more conditions to indicate when a branch should be executed. A condition in aa shell script can involve numeric
values or text values. A condition is typically enclosed within a set of double brackets [[ ]]. There must be a space
before and after each double bracket. Otherwise the script may not function properly.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 8
When comparing numeric values or text values in a condition, you can use the comparison operators listed in the
table below. Be careful to include space before and after the operator to separate the operator from the variables
and/or values on its left and right side. Otherwise, the shell may incorrectly evaluate the condition
Shell script supports logical operators such as OR and AND to specify a compound condition such as condition that
contain multiple comparisons. You can also use logical not to negate a condition. Table below shows the logical
operator with example of their use.
Taking a look at a simple one-branch decision shown below, shows how to specify a simple branch statement with if-
then-fi. The example below takes two numbers and reports if the first one is smaller than the other one.
For a situation that requires more than one condition and/or more than two branches. You can incorporate elif
statement into one of the previous decision structure. The example below shows the use of if-then-elif-then-else
statement. The condition for elif statement is same as if statement.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 9
read -p “Enter First Number: ” num1 read -p “Enter
Second Number: ” num2 if [[ $num1 < $num2 ]]; then
echo “$num1 is smaller than $num2” elif [[ $num1 >
$num2 ]]; then echo $num1 “is greater than”
$num2 else echo $num1 “is equal to” $num2 fi
While all the previous examples with if statement and conditions involved numeric variables and values, you can also
compare text variables and text values with the operator listed previously. Such text comparisons refer to the ASCII
value of the individual text characters on left and right sides. Here the first character is compared, followed by the
second then the third and so on. Until it can determine whether the given comparison is true or false. Additionally,
keep in mind that text is considered case sensitive and capital letters have lower ASCII values than the lowercase
counterparts.
Consequently, a comparison of two string is true when both sides have exactly same text and case. The example
below shows how to use text variable in string comparison however, the example below may exist potential error.
if [[ $YN = ‘YES’ ]]; then
else
However, imagine that $YN has no value then the condition becomes [[ = ‘YES’ ]], resulting in a runtime error where
the shell script does not execute correctly. To fix this problem you need to treat both sides of the comparisons as a
string with an added letter. To ensure that each side contains at least one letter. The fix is demonstrated in an
example below.
In the script above we have added the letter ‘x’ on both sides however, it could have been any other letter. The
reason of adding an extra letter on both sides is because how a shell script interprets the script contents as it
executes the script content. In this case, when executing if statement using any variable the shell script uses its value
rather than the variable. If the variable is empty, the side of that comparison is considered empty hence resulting in a
runtime error generated by the shell executing that script.
In a situation where you wish to compare the text variable’s value without distinguishing of being upper case or
lower case. One can use logical operator to compare against both lowercase and uppercase forms of the text. The
example of this demonstration is shown below.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 10
read -p “Enter y (yes) or n (no): ” YN
if [[ “x$YN” = “xy” || “x$YN” = “xY” ]]; then
echo “you specified yes” else
echo “you specified no”
fi
Another form of a condition containing numeric variables or values involves the test operator. It allows you to specify
a numeric condition by omitting enclosing brackets entirely and preceding the word test. The example below
demonstrates the test command to determine whether one numeric variable contain smaller value than the other
one.
‘case’ Structure
Alternative form of shell script branching involves case structure. It allows the specification of a controlling value by a
case statement. Following the case statement is a series of values or patterns, each with a branch of one or more
statements. Like switch-case structure in C/C++, the shell compares the controlling value against the values to find a
match, starting with the first and continuing till the last. When a match is found, the shell executes the corresponding
branch. You can also include a default branch that is executed if the controlling value does not mtch any of the values
or pattern.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 11
read -p “Enter the starting balance: ” balance
echo “Menu options” echo “
a) Deposit” echo “ b)
Withdraw”; echo
read -p “Enter your selection: ” selection case $selection in
a|A) read -p “Enter the deposit amount: ” deposit
((balance = $balance + $deposit))
;;
Iterative Structure
To accomplish iteration in a shell script, you have a number of mechanisms available for that purpose. These involves
while loops, for loops and a form of while loop called until. The syntax of these stated iterative loops is shown below.
Example of utilizing while loop, the below examples takes then number of directories to be created then using while
loop it takes the names of those directories from user and tries to create them.
The utilization of for loop of the same script requirement is demonstrated in an example below.
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 12
for i in {1..4} do read -p “Enter the name of the
directory: ” dirName mkdir $dirName
if [[ $? = 1 ]] ; then echo
“Directory creation failed” fi
done
The demonstration of the form of while loop aka until is shown below
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 13
Functions
To help modularize and reuse shell script code, you can use functions within a shell script like you can in other
programming languages. A short example shows a shell script that defines a function named ‘Min’ that prints the
smaller of two arguments. The script asks the user to input two numbers and calls the Min function to report the
smaller number from the two provided.
else
Smallest=$2
fi
}
read -p “Enter two whole numbers, Separated by space: ” N1 N2 Min
$N1 $N2
echo “The smallest is: ” $Smallest
At first line of a function definition, it specifies the function name and an empty set of parentheses. Unlike many
other programming languages, the parentheses at the first line of a function definition are always empty, whether or
not you supply arguments to the function. The remainder of the function definition consists of the commands in the
function body enclosed with { and } braces. To access any arguments with a function, use the shell script variable
explained in ‘Accessing Arguments’ section.
Special Symbols
The following are the meaning of symbols used in shell scripting:
LAB#02: SHELL SCRIPTING & VI, ALIASES, ENVIRONMENT VARIABLES AND SUBSHELLS 14
Introduction to
Shell Scripting with Bash
Charles Jahnke
Research Computing Services
Information Services & Technology
Topics for Today
● Introductions
● Basic Terminology
● How to get help
● Command-line vs. Scripting
● Variables
● Handling Arguments
● Standard I/O, Pipes, and Redirection
● Control Structures (loops and If statements)
● SCC Job Submission Example
Me
● Contact: help@scc.bu.edu
Basic Terminology
The Command-line
The line on which commands are typed and passed to the shell.
[username@scc1 ~]$
● Provides:
○ Built-in commands
○ Programming control structures
○ Environment variables
Script
● A text file containing a series of commands that an interpreter (like shell) can
read and run.
Interpreter
● A program that runs commands without compiling (directly from text)
Bash
The name of the most common shell interpreter, it’s language, and syntax.
SYNOPSIS This text is a brief description of the features that are present in the
bash [options] [file] Bash shell (version 4.2, 28 December 2010).
COPYRIGHT This is Edition 4.2, last updated 28 December 2010, of 'The GNU Bash
Bash is Copyright (C) 1989-2011 by the Free Software Reference Manual', for 'Bash', Version 4.2.
Foundation, Inc.
Bash contains features that appear in other popular shells, and some
DESCRIPTION features that only appear in Bash. Some of the shells that Bash has
Bash is an sh-compatible command language interpreter borrowed concepts from are the Bourne Shell ('sh'), the Korn Shell
that executes commands read from the standard input or ('ksh'), and the C-shell ('csh' and its successor, 'tcsh'). The
from a file. Bash also incorporates useful features from following menu breaks the features up into categories based upon which
the Korn and C shells (ksh and csh). one of these other shells inspired the feature.
Bash is intended to be a conformant implementation of the This manual is meant as a brief introduction to features found in
Shell and Utilities portion of the IEEE POSIX specifica- Bash. The Bash manual page should be used as the definitive reference
tion (IEEE Standard 1003.1). Bash can be configured to on shell behavior.
be POSIX-conformant by default.
* Menu:
Bash “help”
scc1 $ help forhelp
● Bash comes with built in help functionality GNU bash,
help:
for: for
helpNAME
version
[-dms]
[in WORDS
4.2.46(2)-release
[pattern......]
] ; do COMMANDS;
(x86_64-redhat-linux-gnu)
done
TheseDisplay
Execute
shell commands
informationareabout
for defined
each builtin
member
internally.
incommands.
a list. Type `help' to see this list.
○ Just type “help”
Type `help name' to find out more about the function `name'.
Use The
`info
Displays
`for'
bash'
brief
loop
to executes
find out a
summaries more
of
sequence
builtin
about of the
commands.
commands
shell infor
If
general.
PATTERN
each member
is in a
Use list
`man of
specified,
-k'items.
orgives
`info'If
detailed
to find
`in WORDS
help
out
...;'
more
on all
is
about
commands
not commands
present,
matching
not in
then PATTERN,
`in
this
"$@"'
list.
is
● Read deeper into help chapters by otherwise For
assumed. the each
list element
of help in topics
WORDS,is NAME
printed.
is set to that element, and
A star
the(*)
COMMANDS
next toare
a executed.
name means that the command is disabled.
searching specific keywords Options:
job_spec
Exit
-d Status:
[&] output short descriptionhistoryfor [-c]each
[-dtopic
offset] [n] >
○ “help [keyword]” (( Returns
expression
-m the))
displayof
status usage
the last
in pseudo-manpage
if
command
COMMANDS;
executed.
then
format
COMMANDS; [>
for
. filename
((:
-sfor (([arguments]
exp1;
output exp2;
onlyexp3
a short
));jobs
usage
do [-lnprs]
COMMANDS;
synopsis[jobspec
done
for each
...]
topic
o> matching
: Arithmetic
PATTERNfor loop. kill [-s sigspec | -n signum >
[ arg... ] let arg [arg ...]
[[ Equivalent
expression to
Arguments: ]] local [option] name[=value] .>
aliasPATTERN
[-p]
(( EXP1
[name[=value]
Pattern specifiying
)) ... ]> logout a help [n]
topic
● “Help help” bg [job_spec
bindExit
while ((
[-lpvsPVS]
...]EXP2 )); do
Status:COMMANDS
mapfile [-n count] [-O origin>
[-m keymap] [-> popd [-n] [+N | -N]
● “Help for” ...Returns success
given.
.. done
(( EXP3
unless
)) PATTERN is not found or an invalid option is
https://www.gnu.org/software/bash
Command-line vs. Scripting
Recap of Command Line vs Script Definitions
Command-line
● Has a prompt
● Not saved
● One line at a time
● The text based way to interact with a computer
Script
● No prompt
● Is a file
● Still runs one line at a time
● Runs all the lines in file without interaction
Example CLI Task: Organize some downloaded data
[username@scc1 ~]$ cd /projectnb/scv/jpessin/introToBashScripting_sampleScripts/cli_script
[username@scc1 cli_script]$ ls data
LICENSE sample1.chr1.bam sample1.chr4.bam sample2.chr1.bam sample2.chr4.bam sample3.chr1.bam sample3.chr4.bam
README sample1.chr2.bam sample1.chr5.bam sample2.chr2.bam sample2.chr5.bam sample3.chr2.bam sample3.chr5.bam
report.html sample1.chr3.bam sample1.log sample2.chr3.bam sample2.log sample3.chr3.bam sample3.log
[username@scc1 cli_script]$ cd data
[username@scc1 data]$ mkdir sample1
[username@scc1 data]$ mv sample1.chr*.bam > sample1
-bash: sample1: Is a directory
[username@scc1 data]$ mv sample1.chr*.bam sample1/
[username@scc1 data]$ cd sample1/
[username@scc1 sample1]$ ls sample1.* > sample1.fileset.txt
[username@scc1 sample1]$ less sample1.fileset.txt
[username@scc1 sample1]$ mv sample1.fileset.txt ../
[username@scc1 sample1]$ cd ..
[username@scc1 data]$ ls
LICENSE sample1 sample2.chr1.bam sample2.chr4.bam sample3.chr1.bam sample3.chr4.bam
README sample1.fileset.txt sample2.chr2.bam sample2.chr5.bam sample3.chr2.bam sample3.chr5.bam
report.html sample1.log sample2.chr3.bam sample2.log sample3.chr3.bam sample3.log
Example CLI Task (cont.)
[username@scc1 data]$ ls
LICENSE sample1 sample2.chr1.bam sample2.chr4.bam sample3.chr1.bam sample3.chr4.bam
README sample1.fileset.txt sample2.chr2.bam sample2.chr5.bam sample3.chr2.bam sample3.chr5.bam
report.html sample1.log sample2.chr3.bam sample2.log sample3.chr3.bam sample3.log
[username@scc1 data]$ mkdir sample2
[username@scc1 data]$ mv sample2.chr*.bam sample2
[username@scc1 data]$ mkdir sample3
[username@scc1 data]$ mv sample3.chr*.bam sample3
[username@scc1 data]$ ls
LICENSE report.html sample1.fileset.txt sample2 sample2.log sample3.fileset.txt sample4 sample4.log
README sample1 sample1.log sample2.fileset.txt sample3 sample3.log sample4.fileset.txt
[username@scc1 data]$ mkdir logs
[username@scc1 data]$ mv sample*.log logs/
[username@scc1 data]$ rm LICENSE
rm: remove regular empty file 'LICENSE'? y
[username@scc1 data]$ rm README
rm: remove regular empty file 'README'? y
[username@scc1 data]$ ls
logs sample1 sample2 sample3 sample4
report.html sample1.fileset.txt sample2.fileset.txt sample3.fileset.txt sample4.fileset.txt
Command-line Interface
● Difficult to read
● One-directional / Non-reproducible
○ What did I do last time?
○ What should someone do next time?
● Manual
● Potentially error-prone
● Wasn’t really that fast
Write a Script Instead
reorgData.sh
#!/bin/bash scc1 $ ls data
# Take datadir from input LICENSE sample1.chr5.bam sample2.log
datadir=$1 README sample1.log sample3.chr1.bam
report.html sample2.chr1.bam sample3.chr2.bam
cd $datadir
sample1.chr1.bam sample2.chr2.bam sample3.chr3.bam
# Detect number of samples sample1.chr2.bam sample2.chr3.bam sample3.chr4.bam
numSamples=$(ls sample*.bam | cut -d. -f1 | uniq | wc -l)
sample1.chr3.bam sample2.chr4.bam sample3.chr5.bam
# Reorg sample files into sample dirs sample1.chr4.bam sample2.chr5.bam sample3.log
for sampleNum in $(seq 1 $numSamples); do
mkdir sample$sampleNum
mv sample$sampleNum*.chr*.bam sample$sampleNum/ scc1 $ bash reorgData.sh data/
ls sample$sampleNum > sample$sampleNum.filelist.txt
done scc1 $ ls data
# Organize Logs logs sample1 sample2 sample3
mkdir logs report.html sample1.files sample2.files sample3.files
mv sample*.log logs/
scc1 $ ls -l
Files can be made “executable” on their own. drwxr-sr-x 6 cjahnke scv 32768 Jun 1 2:36 data
-rw-r--r-- 1 cjahnke scv 453 Jun 1 2:37 reorgData.sh
To do this, we need to:
scc1 $ chmod +x reorgData.sh
scc1 $
Variables
Environment Variables
scc1 $ echo $USER
● Contain environment configuration cjahnke
○ Typically for the shell, but other programs can scc1 $ echo $PWD
set their own.
/usr3/bustaff/cjahnke
● Created automatically when logged in.
scc1 $ echo $HOSTNAME
● Scope is global scc1
○ Other programs can read/use them to know
how to behave.
scc1 $ env
MODULE_VERSION_STACK=3.2.10
XDG_SESSION_ID=c8601
HOSTNAME=scc1
TERM=xterm
SHELL=/bin/bash
● Type “env” to see the full list. HISTSIZE=1000
TMPDIR=/scratch
SSH_CLIENT=128.197.161.56 55982 22
...
scc1 $ myvar=foo
scc1 $ echo $myvar
Shell Variables foo
scc1 $ myvar=bar
scc1 $ echo $myvar
● A character string to which a user bar
● lowercase
○ Effective for simple scripts, hard to read if names are complicated (e.g. $mynewvar).
● Under_scores
○ Common alternative to spaces (e.g. $my_new_var). Bash does not accept hyphens.
● camelCase
○ Capitalization patterns are concise and easy enough to read (e.g $myNewVar).
Using variables: The dollar sign and quotes
scc1 $ hi=Hello
● No quote
○ Simple. Bash shell interprets variable scc1 $ echo $hi
● Escape Special Character (“\”) Hello
○ The “$” is special and indicates a variable in
Bash. The “\” escapes special behavior and scc1 $ echo \$hi
instructs bash to treat it as a character. $hi
● Single Quote
scc1 $ echo '$hi'
○ Literal. Exactly the contents.
$hi
● Double Quote
○ Interpreted. Allows variable expansion. scc1 $ echo "$hi"
Hello
Using Variables: Strings, spaces, and quotes
scc1 $ hello0=Hello World
-bash: World: command not found
scc1 $ echo $hello0
Hello
Spaces are special too
scc1 $ hello1=Hello\ World
● We can escape (“\”) the special behavior
scc1 $ echo $hello1
● Or we can quote the string. Hello World
○ Single or double quotes are effectively the
same if there is nothing to be interpreted. scc1 $ hello2='Hello World'
scc1 $ echo $hello2
Hello World
scc1 $
Handling Arguments
Command-line Arguments in Bash
The command used to start a bash script passes the command information to the
script as variables when it runs. This information is accessed through numbered
variables where the “#” is the index of the information.
Note: only 9 arguments are captured; after that, you need to be creative.
Simple Command Line Argument Example
cli_arg.sh Terminal
#!/bin/bash scc1 $
* What they are actually used for is entirely dependent on the program
TERMINAL
written files
Keyboard
Process 1
STDOUT
2 Display
STDERR
Standard Out & Standard Error
scc1 $ man
scc1 $ man What manual page do you want?
● Example:
[cjahnke@scc1 ~]$ cat sample.vcf | cut -f1,2,7 | sort -k3
#CHROM POS ID REF ... #CHROM POS FILTER #CHROM POS FILTER
3 14370 rs6054257 G ... 3 14370 PASS 1 1110696 PASS
2 17330 . T ... 2 17330 q10 3 1230237 PASS
1 1110696 rs6040355 A ... 1 1110696 PASS 3 14370 PASS
3 1230237 . T ... 3 1230237 PASS 6 1234567 PASS
6 1234567 microsat1 GTCT ... 6 1234567 PASS 2 17330 q10
Redirection
● The “>” symbol redirects the standard output (default) of a command to a file.
Redirection Description
COMMAND < filename Input - Directs a file
COMMAND << stream Input - Directs a stream literal
COMMAND <<< string Input - Directs a string
COMMAND > filename Output - Writes output to file (will “clobber”)
COMMAND >> filename Output - Appends output to file
● Example:
[cjahnke@scc1 ~]$ cat sample.vcf | cut -f1,2,7 | sort -k3 > sorted.txt
Many characters use or modify this behavior
● A < file Use the contents of file as input for A
● B > file Create a new file and write the standard out of B there (overwrites)
● C >> file If file exists append standard out of C to file, if file does not exist create it
● D 2> file Create a new file and write the standard err of D there
● E &> file Combined the standard error and standard out and write to file
● F|G Use the standard out of F as the standard in of G
● H |& K Combine the standard out and err of H and use as the standard in of K
● M | tee file Write the standard out of M to both the terminal and to file
scc1 $
For Loop (In Practice)
Let’s iterate on something more interesting
scc1 $ bash forloop1.sh a b c
● Input Items can be called with $@ a
b
c
#!/bin/bash
scc1 $ bash forloop1.sh a "b c" d
# This loop iterates over input items
a
for input in "$@"; do b c
echo "$input" d
done
For Loop (In Practice)
#!/bin/bash scc1 $ bash forloop2.sh ~/bash
forloop2.sh
# This script takes one argument, a
# directory, and prints the basename of
# contents. /usr3/bustaff/cjahnke/bash
forloop1.sh
echo $0 forloop2.sh
echo "" myscript.sh
echo $1
https://google.github.io/styleguide/shell.xml#Loops
Conditional Constructs
● test “[[ .. ]]”
○ Evaluates expression inside brackets and returns 0 (TRUE) or 1 (FALSE)
● if
○ Executes commands following conditional logic.
● case
○ Selectively execute commands corresponding to pattern matching.
○ Like if/then statements, but usually used for parsing inputs and determining flow.
● select
○ Used for creating user input/selectable menus, executes commands on selection.
● Arithmetic “(( .. ))”
○ Will perform arithmetic. Use caution, precision can be tricky.
Tests “[[ .. ]]”
Double square brackets return an exit status of scc1 $ [[ 1 == 1 ]] ; echo $?
0 (true) or 1* (false) depending on the 0
evaluation of the conditional expression inside.
scc1 $ [[ 1 == 2 ]] ; echo $?
1
● Standard Test
○ [[ expression ]]
scc1 $ [[ ! cow == dog ]]; echo $?
● Negative Test
0
○ [[ ! expression ]]
● AND Test
scc1 $ [[ 1 == 2 && cow == cow ]]; echo $?
○ [[ expression1 && expression2 ]]
1
● OR Test
○ [[ expression1 || expression2 ]]
scc1 $ [[ 1 == 1 || cow == dog ]]; echo $?
0
* Anything >=1 is considered false. Programs may have many possible exit codes. 0 is success, everything else is a descriptive error.
If Statement (Simple)
● An “if“ statement executes commands
based on conditional tests.
$ cp /projectnb/scv/bash_examples.tar .
$ tar xf bash_examples.tar
$ cd bash_examples
$ ls
done
done
returns:
Scripting in bash makes many many things much easier, like putting this
sentence together.
SCC Job Submission Example
using a loop to submit jobs on SCC with names.
$ for file in *_1.txt; do echo "$file" >>
step 1 create a file with the names
filenames.txt; done
$ cat filenames.txt
AG_1.txt
aA_1.txt
ab_1.txt
ac_1.txt
ad_1.txt
af_1.txt
ag_1.txt
ah_1.txt
ai_1.txt
aj_1.txt
order_1.txt
outof_1.txt
using a loop to submit jobs on SCC with names.
$ for file in *_1.txt; do echo "$file" >>
step 1 create a file with the names
filenames.txt; done
$ cat filenames.txt
step 2 get the number of filenames AG_1.txt
aA_1.txt
ab_1.txt
ac_1.txt
ad_1.txt
af_1.txt
ag_1.txt
ah_1.txt
ai_1.txt
aj_1.txt
order_1.txt
outof_1.txt
$ wc -l filenames.txt
12 filenames.txt
using a loop to submit jobs on SCC with names.
#!/bin/bash -l
step 1 create a file with the names
#$ -P tutorial
step 2 get the number of filenames
value1=$(cat "$1")
step 3 create a submission script that value2=$(cat "$2")
accepts inputs (remember to chmod +x)
valueNew=$(( $value1 + $value2 ))
step 5 submit
CL2006 - Operating Systems Spring 2024
LAB # 3 MANUAL (Common)
Please note that all labs’ topics including pre-lab, in-lab and post-lab exercises are part of the
theory and labsyllabus. These topics will be part of your Midterms and Final Exams of lab and
theory.
Objectives:
1. Use your existing knowledge of Linux command line and C programming (PF, OOPs, Data Structures) to
learn linux bash shell scripting to automate basic Linux jobs.
2. You should be able to write an error free Linux bash shell script given a problem description.
Lab Tasks:
Strictly following the following content delivery strategy. Ask students to take notes during the lab.
1st Hour
- Pre-Lab (up to 15 minutes)
- Explain importance and history of shell scripting. Command-line vs Shell Scripting. (15 minutes)
- Ask students to type of run Task # 1 (15 minutes). Observe their weaknesses and back scripting command
which you can cover from Handout # 1 and/or Handout # 2.
2nd Hour
- Cover Handout # 2. Few of you can cover details from Handout # 1 (keep this session within 45 minutes).
- Ask students to type and execute Task # 2 (15 minutes)
3rd Hour
- Devote full hour doing the in-lab problem. (60 minutes)
** ChatGPT is heavily used to make the contents of this document along with other Internet sources.
Lab
Lab # 3 Manual
EXPERIMENT 3
Creating, Executing LINUX Bash Shell Script
With the widespread adoption of Linux, shell scripting became an essential tool for automating tasks, executing
multiple commands sequentially, and performing various system administration tasks. Bash scripting became
the most used scripting language on Linux systems due to its availability and compatibility with POSIX
standards. A Linux Bash shell script is a text file containing a series of commands written in the Bash
scripting language. Bash (Bourne Again Shell) is a popular command-line interpreter and scripting language
for Unix-like operating systems, including Linux. Bash scripts can incorporate control structures such as
loops and conditional statements, variables, functions, and command-line arguments to enhance their
functionality.
1. Bourne Shell (sh): - Became the de facto standard shell for Linux
- Developed by Stephen Bourne at AT&T Bell systems due to its ubiquity and powerful scripting
Laboratories in the early 1970s. capabilities.
- Became the default shell for Unix systems.
- Provided basic scripting capabilities with loops, 5. Other Shells:
conditionals, and command execution. - Several other shells exist, including tcsh (an
enhanced version of C Shell), zsh (Z Shell), and fish
2. C Shell (csh): (Friendly Interactive Shell), each with its own
- Developed by Bill Joy at the University of features and syntax.
California, Berkeley, in the late 1970s.
- Featured a C-like syntax and interactive features
such as command history and job control.
- Popular among users who preferred its
interactive features.
Page 2 of 6
Lab
Lab # 3 Manual
#!/bin/bash
SRC_DIR=/path/to/source/directory
DST_DIR=/path/to/backup/directory
if [ ! -d "$DST_DIR" ]; then
mkdir -p "$DST_DIR"
fi
if [ ! -d "$SRC_DIR" ]; then
echo "Error: Source directory does not exist"
exit 1
fi
Description
1. Variable Declarations:
- `SRC_DIR=/path/to/source/directory`: Defines a variable `SRC_DIR` containing the path to the source
directory.
- `DST_DIR=/path/to/backup/directory`: Defines a variable `DST_DIR` containing the path to the backup
directory.
4. Error Handling:
- `if [ ! -d "$SRC_DIR" ]; then`: Checks if the source directory (`$SRC_DIR`) does not exist.
- `echo "Error: Source directory does not exist"`: If the source directory does not exist, prints an error message.
- `exit 1`: Exits the script with a non-zero status code (1) to indicate an error.
Page 3 of 6
Lab
Lab # 3 Manual
#!/bin/bash
process_data() {
input_file=$1
output_file=$(cut -f 1,3 $input_file | grep 'foo' | sort -n)
echo $output_file
}
for file in /path/to/files/*.txt; do
processed_data=$(process_data $file)
echo $processed_data > "${file}_processed.txt"
done
Description
1. Function Definition (`process_data`):
- `process_data() { ... }`: Defines a function named `process_data` for processing input data.
2. Function Argument:
- `input_file=$1`: Assigns the first argument passed to the function (`$1`) to the variable `input_file`.
3. Data Processing:
- `output_file=$(cut -f 1,3 $input_file | grep 'foo' | sort -n)`: Processes the data from the input file using a
series of command-line tools:
- `cut -f 1,3 $input_file`: Extracts the first and third fields from the input file using the `cut` command.
- `grep 'foo'`: Filters the extracted data to include only lines containing the string 'foo' using the `grep`
command.
- `sort -n`: Sorts the filtered data numerically using the `sort` command.
6. Function Call:
- `processed_data=$(process_data $file)`: Calls the `process_data` function with the current file as an
argument (`$file`) and captures the output in the variable `processed_data`.
Page 4 of 6
Lab
Lab # 3 Manual
In-Lab
Consider the following log file data entries:
Now you are tasked with creating a shell script to analyze log files generated by a web server. The script
should perform the following tasks:
Sample solution:
#!/bin/bash
# Log File Analyzer
# Accept log file as input
log_file="$1"
# Count total number of requests
total_requests=$(wc -l < "$log_file")
# Determine number of unique IP addresses
unique_ips=$(awk '{print $1}' "$log_file" | sort -u | wc -l)
# Identify top 5 most frequent IP addresses
top_ips=$(awk '{print $1}' "$log_file" | sort | uniq -c | sort -nr | head -5)
# Calculate total size of data transferred
total_size=$(awk '{sum += $10} END {print sum}' "$log_file")
# Generate summary report
echo "Log File Analysis Report" > analysis_report.txt
echo "-------------------------" >> analysis_report.txt
echo "Total Requests: $total_requests" >> analysis_report.txt
echo "Unique IP Addresses: $unique_ips" >> analysis_report.txt
echo "Top 5 IP Addresses:" >> analysis_report.txt
echo "$top_ips" >> analysis_report.txt
echo "Total Size of Data Transferred: $total_size bytes" >> analysis_report.txt
echo "Report generated on: $(date)" >> analysis_report.txt
Page 5 of 6
Lab
Lab # 3 Manual
Post-Lab
You are tasked with creating a bash script that renames multiple files in a directory according to a
specified naming convention. The script should:
a. Accept two arguments: the directory path containing the files and the new file name pattern.
b. Rename each file in the directory by appending a sequential number to the new file name
pattern (e.g., `file1.txt`, `file2.txt`, etc.).
c. Preserve the original file extension during the renaming process.
d. Provide feedback to the user about the renaming process, including any errors encountered.
Develop a bash script to automate directory cleanup tasks by removing old files and directories. The
script should:
Create a bash script to monitor system resources and generate a report. The script should:
a. Collect information about CPU usage, memory usage, disk space, and network traffic.
b. Calculate average values for each resource over a specified time period.
c. Generate a report containing the collected data and average values.
d. Provide options for the user to customize the time period and output format of the report.
Page 6 of 6
CL2006 - Operating Systems Spring 2024
LAB # 4 MANUAL (Common)
Please note that all labs’ topics including pre-lab, in-lab and post-lab exercises are part of the theory
and labsyllabus. These topics will be part of your Midterms and Final Exams of lab and theory.
Objectives:
2. Implement system calls such as fork (), wait(), exit(), exec(), sleep(), getpid(), getppid(), alarm(),
open(), read(), write(), and close() to perform essential operating system tasks.
Lab Tasks:
Strictly following the following content delivery strategy. Ask students to take notes during the lab.
1st Hour
- Pre-Lab (up to 15 minutes)
- System Call introduction (15 minutes)
- C program structure for making system calls (30 minutes)
2nd Hour
- Process management (60 minutes)
3rd Hour
- Information retrieval, and File manipulation (60 minutes)
Initial Document: Hamza Yousuf (January 2019). This version by: Nadeem Kafi (09/02/2024)
DEPARTMENT OF COMPUTER SCEICEN, FAST-NU, KARACHI
** ChatGPT is heavily used to make the contents of this document along with other Internet sources.
Lab
Lab # 4 Manual
EXPERIMENT 4
System Calls
What are system calls?
A system call is a mechanism that allows a user-level program to request a service or operation
from the kernel (the core part of the operating system). These services can range from low-level
tasks like accessing hardware devices to higher-level operations like creating or terminating
processes.
1. Communication with the Kernel: The kernel is the central component of an operating
system responsible for managing hardware resources and providing essential services to user
programs. User programs, including applications and utilities, operate in a restricted
environment known as user mode. Direct access to hardware resources is prohibited in user
mode for security and stability reasons.
2. Transition to Kernel Mode: When a user program requires a service that only the operating
system kernel can provide, it needs to transition from user mode to a more privileged mode
called kernel mode. System calls provide a controlled mechanism for this transition. When a
system call is invoked, the program switches from user mode to kernel mode to execute the
requested operation.
3. Requesting Operating System Services: System calls act as an interface between user
programs and the operating system kernel. They allow user programs to request various
services or operations provided by the kernel. Examples of common system calls include:
▪ Opening, reading from, writing to, and closing files.
▪ Creating, executing, and terminating processes.
▪ Allocating and managing memory.
▪ Interacting with hardware devices such as printers and network interfaces.
4. Implementation by the Kernel: Each system call has a unique identifier or number
associated with it, known as a syscall number. This number is used by the kernel to identify
the requested service. The kernel contains implementations for handling different system
calls. When a system call is invoked, the kernel executes the corresponding routine to perform
the requested operation.
5. Return Values and Error Handling: System calls typically return a value to the calling
program, indicating the success or failure of the requested operation. If an error occurs during
the execution of a system call, the kernel returns a special error code, allowing the user
program to handle the error gracefully.
Page 2 of 8
Lab
Lab # 4 Manual
C program structure for doing System Calls
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int main () {
// Declare variables and necessary data structures
return 0;
}
This basic structure provides a framework for writing C programs that utilize explicit Linux/UNIX
system calls, enabling developers to interact directly with the underlying operating system for
performing various tasks. Explanation of various part of the programs follows:
• #include <stdio.h>: The standard input-output library for basic input and output operations.
• #include <stdlib.h>: The standard library for general utilities and memory allocation.
• #include <unistd.h>: The POSIX (Portable Operating System Interface) standard header file
for various system calls, such as process management (fork(), exec(), exit(), etc.).
• #include <sys/types.h>: Definitions for various data types used in system calls, such as pid_t
for process IDs.
• #include <sys/wait.h>: Definitions for functions related to process management and waiting
for child processes to terminate.
• #include <errno.h>: Definitions for error numbers that may occur during system calls.
o Declare necessary variables and data structures for holding information related to system
calls and their results.
o Make explicit system calls as required for the intended functionality of the program. These
system calls could involve process management, file operations, memory allocation, etc.
o Handle errors that may occur during system calls using error-checking mechanisms like
errno and appropriate error-handling techniques.
o Perform necessary operations using the results obtained from system calls.
Page 3 of 8
Lab
Lab # 4 Manual
Process Creation:
The processes in most systems can execute concurrently, and they may be created and deleted
dynamically. Thus, these systems must provide a mechanism for process creation and termination.
1. fork()
• Has a return value.
• Parent process => invokes fork () system call
• Continue execution from the next line after fork ()
• Has its own copy of any data.
• Return value is > 0 //it’s the process id of the child process. This value is different.
from the Parents own process id.
• Child process => process created by fork() system call
• Duplicate/Copy of the parent process //LINUX
• Separate address space
• Same code segments as parent process
• Execute independently of parent process
• Continue execution from the next line right after fork()
• Has its own copy of any data
• Return value is 0
2. wait ()
• Used by the parent process
• Parent’s execution is suspended
• Child remains its execution
• On termination of child, returns an exit status to the OS
• Exit status is then returned to the waiting parent process //retrieved by wait ()
• Parent process resumes execution
• #include <sys/wait.h>
• #include <sys/types.h>
3. exec()
• The exec() system call replaces the current process image with a new process image, which means
it loads a new program into memory and starts its execution. Called by an already existing process.
• It has several variants, such as execl(), execv(), execle(), execve(), etc., each with different ways of
passing arguments to the new program.
• Here are the general steps involved in using the exec() system call:
▪ Open the Target Program File: The first step is to locate and open the file of the program you
want to execute. This could be a binary executable file, a script, or any other executable file.
▪ Load the Program into Memory: The exec() system call loads the program into the current
process's memory space, replacing the current program image.
▪ Set Up Execution Context: The system sets up the execution context for the new program,
including initializing the program counter, setting up the stack, and preparing other resources
needed for execution.
▪ Start Execution: Finally, the new program starts its execution from its entry point, as defined in
its binary executable file.
• Has an exist status but cannot return anything (if exec() is successful) to the program that
made the call i.e. parent process
• Return value is -1 if not successful.
• Overlay => replacement of a block of stored instructions or data with another.
int execlp(char const *file_path, char const *arg0, );
• Arguments beginning at arg0 are pointers to arguments to be passed to the new
process.
Page 4 of 8
Lab
Lab # 4 Manual
• The first argument arg0 should be the name of the executable file.
• Example: execlp( /bin/ls , ls ,NULL) //lists contents of the directoryHeader file used -> unistd.h
4. exit():
• The exit() system call is used to terminate a process immediately from any point within the
program, not just within the main() function. EXIT_SUCCESS // integer value = 0,
EXIT_FAILURE // integer value = 1
• It takes an integer argument known as the exit status, which is returned to the parent process or
environment to indicate the termination status of the program.
• The exit() system call performs cleanup tasks, such as closing open files and releasing allocated
memory, before terminating the process.
• Calling exit() directly causes the program to exit immediately from the point where it is called,
bypassing any further execution of the program.
• Process related:
- It returns exit status, which is retrieved by the parent process using wait () command.
- OS reclaims resources allocated by the terminated process (dead process) Typically
performs clean-up operations within the process space before returning control.
- Terminates the current process without any extra program clean-up.
- Usually used by the child process to prevent from erroneously release of resources
belonging to the parent process.
Information Maintenance:
i. sleep()
• Process goes into an inactive state for a time period
• Resume execution if
• Time interval has expired
• Signal/Interrupt is received
• Takes a time value as parameter (in seconds on Unix-like OS and inmilliseconds
on Windows OS)
• sleep(2) // sleep for 2 seconds in Unix
• Sleep(2*1000) // sleep for 2 seconds in Windows
iii. alarm()
• Use to set an alarm timer for a process. It takes an argument representing the number of seconds
after which the alarm signal will be delivered to the calling process.
• The signal, known as SIGALRM, interrupts the normal execution of the process and can be used
to perform specific actions or handle timeouts. The program to respond accordingly, such as
terminating the operation or executing a signal handler function.
• Common use cases for alarm() include implementing timeouts for certain operations, scheduling
periodic tasks, or triggering events after a specified delay.
• Additionally, the return value of alarm() provides information about any previously set alarm
timer, allowing programs to query or cancel existing timers as needed. Overall, alarm() is a
Page 5 of 8
Lab
Lab # 4 Manual
versatile system call that facilitates time-based programming and event handling in Unix-based
systems.
File Management:
1. open ()
• Specify File Path and Access Mode: Provide the file path of the file you want to open as well as the
access mode (e.g., read-only, write-only, read-write).
• Check File Permissions: The kernel checks whether the process has the necessary permissions to
open the file based on the access mode specified.
• Locate File Descriptor: If permissions are granted, the kernel locates an available file descriptor (an
integer representing the file) for the file within the process's file descriptor table.
• Open File and Return Descriptor: The kernel opens the file and associates it with the file
descriptor. If successful, it returns the file descriptor to the calling process.
2. read ()
• Specify File Path and Access Mode: Provide the file path of the file you want to open as well as the
access mode (e.g., read-only, write-only, read-write).
• Check File Permissions: The kernel checks whether the process has the necessary permissions to
open the file based on the access mode specified.
• Locate File Descriptor: If permissions are granted, the kernel locates an available file descriptor (an
integer representing the file) for the file within the process's file descriptor table.
• Open File and Return Descriptor: The kernel opens the file and associates it with the file
descriptor. If successful, it returns the file descriptor to the calling process.
3. write ()
• Specify File Descriptor and Data: Provide the file descriptor of the file to which you want to write
data and the data to be written.
• Check File Descriptor Validity: The kernel verifies that the file descriptor provided is valid and
points to an open file.
• Write Data: The kernel writes the specified data to the file associated with the file descriptor.
• Update File Position: After writing, the kernel updates the file position indicator associated with the
file descriptor to reflect the new position in the file.
• Return Number of Bytes Written: The write() system call returns the number of bytes successfully
written to the file to the calling process.
4. close ()
• Specify File Descriptor: Provide the file descriptor of the file you want to close.
• Check File Descriptor Validity: The kernel verifies that the file descriptor provided is valid and
points to an open file.
• Release Resources: The kernel releases any resources associated with the file descriptor, such as
closing the file and freeing memory.
• Invalidate File Descriptor: After closing the file, the kernel invalidates the file descriptor, making it
available for reuse.
• Return Status: The close () system call returns a status indicating whether the file was successfully
closed or if an error occurred to the calling process.
Page 6 of 8
Exercise:
Q1: Write a program that creates two child processes. One child process reads integers from a file
named "data.txt" and calculates their sum, while the other child process reads the same integers and
calculates their average. The parent process waits for both child processes to finish and then prints
the sum and average.
Q2: Write a program that reads a text file named "input.txt" and counts the number of words in it.
Implement error handling for file opening and reading operations. Utilize open(), read(), and close()
system calls.
Q3: Write a Program that Creates n-child process from same parent process using fork() in C
Q4: Write a program that creates three child processes. Each child process performs a specific task:
• The first child process calculates the factorial of a number provided as a command-line
argument.
• The second child process calculates the Fibonacci sequence up to a specified number
provided as a command-line argument.
• The third child process prints the prime numbers up to a specified number provided as
a command-line argument.
• The parent process waits for all child processes to terminate and then prints a message
indicating their completion.
Q5: Develop a program that creates four child processes. Each child process executes a different
command-line utility (ls, ps, whereis, mkdir) using the execlp() function. The parent process waits
for all child processes to complete and then prints a message indicating their completion.
Q6: Develop a program that appends a string provided as a command-line argument to an existing
text file named "data.txt". Implement error handling for file opening and writing operations. Utilize
open(), lseek(), write(), and close() system calls.
Q7. Write Program to create four processes (1 parent and 3 children) where they terminates in a
sequence as
follows:
(a) Parent process terminates at last
(b) First child terminates before parent and after second child.
(c) Second child terminates after last and before first child.
(d) Third child terminates first.