You are on page 1of 80

DYPIEMR, Akurdi.

Department of E&TC

EXP 1 : a. Study of Basic Linux Commands.


TITLE : Linux Basic Commands

AIM : To study basic commands of Linux.

THEORY
Case Sensitivity:
In Linux/UNIX, commands and filenames are case sensitive, meaning that typing “EXIT” instead of the proper
“exit” is a mistake.
􀀀 “\” vs. “/”: In DOS, the forward-slash “/” is the command argument delimiter, while the backslash “\” is a
directory separator. In Linux/UNIX, the “/” is the directory separator, and the “\” is an escape character. More
about these special characters in a minute!

Filenames:
The DOS world uses the “eight dot three” filename convention, meaning that all files followed a format that
allowed up to 8 characters in the filename, followed by a period (“dot”), followed by an option extension, up to
3 characters long (e.g. FILENAME.TXT). In UNIX/Linux, there is no such thing as a file extension. Periods
can be placed at any part of the filename, and “extensions” may be interpreted differently by all programs, or
not at all.

Character Description
\ Escape character. If you want to reference a special character, you must “escape” it with a backslash first.
Example: touch /tmp/filename\*
/ Directory separator, used to separate a string of directory names.
Example: /usr/src/linux
. Current directory. Can also “hide” files when it is the first character in a filename.
.. Parent directory
~ User's home directory
* Represents 0 or more characters in a filename, or by itself, all files in a directory.
Example: pic*2002 can represent the files pic2002, picJanuary2002, picFeb292002, etc.
? Represents a single character in a filename.
Example: hello?.txt can represent hello1.txt, helloz.txt, but not hello22.txt
[ ] Can be used to represent a range of values, e.g. [0-9], [A-Z], etc.
Example: hello[0-2].txt represents the names hello0.txt, hello1.txt, and hello2.txt
| “Pipe”. Redirect the output of one command into another command.
Example: ls | more
> Redirect output of a command into a new file. If the file already exists, over-write it.
Example: ls > myfiles.txt
>> Redirect the output of a command onto the end of an existing file.
Example: echo .Mary 555-1234. >> phonenumbers.txt
< Redirect a file as input to a program.
Example: more < phonenumbers.txt
1
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

; Command separator. Allows you to execute multiple commands on a single line.


Example: cd /var/log ; less messages
&& Command separator as above, but only runs the second command if the first one finished without errors.
Example: cd /var/logs && less messages
& Execute a command in the background, and immediately get your shell back.
Example: find / -name core > /tmp/corefiles.txt &

Executing Commands

The Command PATH:


Most common commands are located in your shell's “PATH”, meaning that you can just type the name of the
program to execute it.
Example: Typing “ ls” will execute the “ ls” command.
Your shell's “PATH” variable includes the most common program locations, such as
/bin, /usr/bin, /usr/X11R6/bin, and others.
To execute commands that are not in your current PATH, you have to give the complete location of the
command. Examples: /home/bob/myprogram
./program (Execute a program in the current directory)
~/bin/program (Execute program from a personal bin directory)

Command Syntax
Commands can be run by themselves or you can pass in additional arguments to make them do different things.
Typical command syntax can look something like this:
command [-argument] [-argument] [--argument] [file]
Examples: ls List files in current directory
ls -l Lists files in “long” format
ls -l --color As above, with colorized output
cat filename Show contents of a file
cat -n filename Show contents of a file, with line numbers

Using a Command's Built-In Help


Many commands have simple “help” screens that can be invoked with special command flags.
These flags usually look like “-h” or “--help”.
Example: grep –help

Online Manuals: “Man Pages”


The best source of information for most commands can be found in the online manual pages, known as “man
pages” for short. To read a command's man page, type “man command”.
Examples: man ls Get help on the “ls” command.
man man A manual about how to use the manual!
To search for a particular word within a man page, type “/word”. To quit from a man page, just type the “Q”
key.

2
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Sometimes, you might not remember the name of Linux command and you need to search for it.
For example, if you want to know how to change a file's permissions, you can search the man page descriptions
for the word “permission” like this:
man -k permission
If you look at the output of this command, you will find a line that looks something like:
chmod (1) - change file access permissions
Now you know that “chmod” is the command you were looking for. Typing “man chmod” will
show you the chmod command's manual page!

Linux Command Description

pwd cd “Print Working Directory”. Shows the current location in the directory tree.
cd cd, chdir “Change Directory”. When typed all by itself, it returns you to your home directory.
cd directory cd directory Change into the specified directory name.
Example: cd /usr/src/linux
cd ~ “~” is an alias for your home directory. It can be used as a shortcut to your “home”, or other directories
relative to your home.
cd .. cd.. Move up one directory. For example, if you are in /home/vic and you type “cd ..”, you will end
up in /home.
cd - Return to previous directory. An easy way to get back to your previous location!
ls dir /w List all files in the current directory, in column format.
ls directory dir directory List the files in the specified directory.
Example: ls /var/log
ls -l dir List files in “long” format, one file per line. This also shows you additional info about the file, such
as ownership, permissions, date, and size.
ls -a dir /a List all files, including “hidden” files. Hidden files are those files that begin with a “.”, e.g. The
.bash_history file in your home directory.
ls -ld
directory A “long” list of “directory”, but instead of showing the directory contents, show the directory's
detailed information. For example, compare the output of the following two commands:
ls -l /usr/bin
ls -ld /usr/bin
ls /usr/bin/d* dir d*.* List all files whose names begin with the letter “d”
in the /usr/bin directory

Piping and Re-Direction


Before we move on to learning even more commands, let's side-track to the topics of piping and
re-direction. The basic UNIX philosophy, therefore by extension the Linux philosophy, is to have
many small programs and utilities that do a particular job very well. It is the responsibility of the
programmer or user to combine these utilities to make more useful command sequences.

3
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Piping Commands Together

The pipe character, “|”, is used to chain two or more commands together. The output of the first
command is “piped” into the next program, and if there is a second pipe, the output is sent to the
third program, etc. For example:
ls -la /usr/bin | less
In this example, we run the command “ls -la /usr/bin”, which gives us a long listing of all
of the files in /usr/bin. Because the output of this command is typically very long, we pipe the
output to a program called “less”, which displays the output for us one screen at a time.

Redirecting Program Output to Files

There are times when it is useful to save the output of a command to a file, instead of displaying it
to the screen. For example, if we want to create a file that lists all of the MP3 files in a directory,
we can do something like this, using the “>” redirection character:
ls -l /home/vic/MP3/*.mp3 > mp3files.txt
A similar command can be written so that instead of creating a new file called mp3files.txt,
we can append to the end of the original file:
ls -l /home/vic/extraMP3s/*.mp3 >> mp3files.txt

Working With Files and Directories


These commands can be used to: find out information about files, display files, and manipulate
them in other ways (copy, move, delete).
file Find out what kind of file it is.
For example, “file /bin/ls” tells us that it is a Linux executable file.
cat type Display the contents of a text file on the screen. For example: cat mp3files.txt would display the file we
created in the previous section.
head Display the first few lines of a text file.
Example: head /etc/services
tail Display the last few lines of a text file.
Example: tail /etc/services
tail -f Display the last few lines of a text file, and then output appended data as the file grows (very useful for
following log files!).
Example: tail -f /var/log/messages
cp Copies a file from one location to another.
Example: cp mp3files.txt /tmp (copies the mp3files.txt file to the /tmp directory)
mv Moves a file to a new location, or renames it.
For example: mv mp3files.txt /tmp (copy the file to /tmp, and delete it from the original location)
rm Delete a file. Example: rm /tmp/mp3files.txt
mkdir Make Directory. Example: mkdir /tmp/myfiles/
rmdir Remove Directory. Example: rmdir /tmp/myfiles/
4
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Finding Things
The following commands are used to find files. “ls” is good for finding files if you already know
approximately where they are, but sometimes you need more powerful tools such as these:

which Shows the full path of shell commands found in your path. For example, if you want to know exactly
where the “grep” command is located on the filesystem, you can type “which grep”. The output should be
something like: /bin/grep
whereis Locates the program, source code, and manual page for a command (if all information is available). For
example, to find out where “ls” and its man page are, type: “whereis ls” The output will look something like: ls:
/bin/ls /usr/share/man/man1/ls.1.gz
locate A quick way to search for files anywhere on the filesystem. For example, you can find all files and
directories that contain the name “mozilla” by typing: locate mozilla
find A very powerful command, but sometimes tricky to use. It can be used to search for files matching certain
patterns, as well as many other types of searches. A simple example is: find . -name \*mp3 This example starts
searching in the current directory “.” and all subdirectories, looking for files with “mp3” at the end of their
names.

Informational Commands
The following commands are used to find out some information about the user or the system.

ps Lists currently running process (programs).


w Show who is logged on and what they are doing.
id Print your user-id and group id's
df Report filesystem disk space usage (“Disk Free” is how I remember it)
du Disk Usage in a particular directory. “du -s” provides a summary for the current directory.
top Displays CPU processes in a full-screen GUI. A great way to see the activity on your computer in real-time.
Type “Q” to quit.
free Displays amount of free and used memory in the system.
cat /proc/cpuinfo Displays information about your CPU.
cat /proc/meminfo Display lots of information about current memory usage.
uname -a Prints system information to the screen (kernel version, machine type, etc.)

Other Utilities
Here are some other commands that are useful to know.
clear Clear the screen
echo Display text on the screen. Mostly useful when writing shell scripts. For example: echo “Hello World”
more Display a file, or program output one page at a time. Examples: more mp3files.txt ls -la | more
less An improved replacement for the “more” command. Allows you to scroll backwards as well as forwards.

5
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

grep Search for a pattern in a file or program output. For example, to find out which TCP network port is used
by the “nfs” service, you can do this: grep .nfs. /etc/services This looks for any line that contains the string “nfs”
in the file “/etc/services” and displays only those lines.
lpr Print a file or program output. Examples: lpr mp3files.txt - Print the mp3files.txt file
ls -la | lpr - Print the output of the “ls -la” command.
sort Sort a file or program output. Example: sort mp3files.txt
su “Switch User”. Allows you to switch to another user's account temporarily.
The default account to switch to is the root/superuser account. Examples:
su - Switch the root account
su - - Switch to root, and log in with root's environment
su larry - Switch to Larry's account

Shortcut Description

When you start using the Bash shell more often, you will appreciate these shortcuts that can save
you very much typing time.

Up/Down Arrow Keys Scroll through your most recent commands. You can scroll back to an old command, hit
ENTER, and execute the command without having to re-type it.
“history” command Show your complete command history.
TAB Completion If you type a partial command or filename that the shell recognizes, you can have it
automatically completed for you if you press the TAB key. Try typing the first few characters of your favourite
Linux command, then hit TAB a couple of times to see what happens.
Complete recent commands with “!” Try this: Type “!” followed by the first couple of letters of a recent
command and press ENTER! For example, type: find /usr/bin -type f -name m\* ...and now type:
!fi
Search your command history with
CTRL-R
Press CTRL-R and then type any portion of a recent command. It will search the commands for you, and once
you find the command you want, just press ENTER. Scrolling the screen with Shift- PageUp and Page Down

Conclusion:
Here we studied about various Linux commands, their description and utilities in brief.

EXP 1 : b. Write a shell scripting on LINUX OS


TITLE : TO IMPLEMENT AN INTERACTIVE SHELL PROGRAMM

AIM : Write an interactive shell program on Linux.


6
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

THEORY

Linux Kernel
The kernel is the heart of the Linux operating system. It manages the resources of Linux such as:
• File management
• Multitasking
• Memory management
• I/O management
• Process management
• Device management
• Networking support including IPv4 and IPv6
• Advanced features such as virtual memory, shared libraries, demand loading, shared copy-on-write
executables etc
The kernel decides who will use these resources and for how long and when. It runs your programs or sets up to
execute binary files. The kernel acts as an intermediary between the computer hardware and various applications.
Linux Shell
Computers understand the language of zeros and ones known as binary language. In the early days of
computing,
instructions were provided using binary language, which is difficult for all of us to read and write. Therefore, in
an
operating system there is a special program called the shell. The shell accepts human readable commands and
translates them into something the kernel can read and process.

What Is a Shell?
• The shell is a user program or it is an environment provided for user interaction.
• It is a command language interpreter that executes commands read from the standard input device such as
keyboard or from a file.
• The shell gets started when you log in or open a console (terminal).
• Quick and dirty way to execute utilities.
• The shell is not part of system kernel, but uses the system kernel to execute programs, create files etc.
• Several shells are available for Linux including:
• BASH ( Bourne-Again SHell ) - Most common shell in Linux. It's Open Source.
• CSH (C SHell) - The C shell's syntax and usage are very similar to the C programming language.
• KSH (Korn SHell) - Created by David Korn at AT & T Bell Labs. The Korn Shell also was the base for the
POSIX Shell standard specifications.
• TCSH - It is an enhanced but completely compatible version of the Berkeley UNIX C shell (CSH).
Please note that each shell does the same job, but each understands different command syntax and provides
different
built-in functions. Under MS-DOS, the shell name is COMMAND.COM which is also used for the same
purposebut it is by far not as powerful as our Linux Shells are!
7
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Fig. A Linux system shell


How to Create a First Shell Script
Shell scripts are short programs that are written in a shell programming language and interpreted by a shell
process. They are extremely useful for automating tasks on Linux and other Unix-like operating systems.
A shell is a program that provides the traditional, text-only user interface for Unix-like operating systems.
Its primary function is to read commands (i.e., instructions) that are typed into a console (i.e., an all-text
display mode) or terminal window (i.e., all-text mode window) and then execute (i.e., run) them. The
default shell on Linux is the very commonly used and highly versatile bash.
A programming language is a precise, artificial language that is used to write computer programs, which
are sets of instructions that can be automatically translated (i.e., interpreted or compiled) into a form (i.e.,
machine language) that is directly understandable by a computer's central processing unit (CPU).
A feature of bash and other shells used on Unix-like operating systems is that each contains a built-in
programming language, referred to as a shell programming language or shell scripting language, which is
used to create shell scripts. Among the advantages of using shell scripts are that they can be very easy to
create and that a large number are already available in books and on the Internet for use with or without
modification for a wide variety of tasks. Shell scripts are also employed extensively in the default
installations of Unix-like operating systems.

A First Script

The following example provides a useful introduction to creating and using shell scripts. The script clears
the monitor screen of all previous lines and then writes the text Good morning, world. on it.

8
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

All that is necessary to create this script is to open a text editor (but not a word processor), such as gedit or
vi, and type the following three lines exactly as shown on a new, blank page:
#! /bin/bash
clear
echo "Good morning, world."
.
After saving this plain text file, with a file name such as morning (or anything else desired), the script is
complete and almost ready to run. Scripts are typically run by typing a dot, a forward slash and the file
name (with no spaces in between) and then pressing the ENTER key. Thus, for example, if the above
script were saved with the name morning, an attempt could be made to execute it by issuing the following
command:
./morning
However, the script probably will not run, in which case an error message will appear on the screen such as
bash: ./morning: Permission denied. This is because the permissions for the file first have to be set to
executable. (By default, the permissions for new files are set to read and write only.) The problem can
easily be solved by using the chmod command with its 755 option (which will allow the file creator to
read, write and execute the file) while in the same directory as that in which the file is located as follows:
chmod 755 morning
Now the script is ready to run by typing the following, again while in the same directory, and then pressing
the ENTER key:
./morning

Variables in Linux
Sometimes to process our data/information, it must be kept in computers RAM memory. RAM
memory is divided into small locations, and each location had unique number called memory
location/address, which is used to hold our data. Programmer can give a unique name to this
memory location/address called memory variable or variable (It’s a named storage location that may
take different values, but only one at a time). In Linux, there are two types of variable
1) System variables - Created and maintained by Linux itself. This type of variable defined in
CAPITAL LETTERS.
2) User defined variables (UDV) - Created and maintained by user. This type of variable defined
in lower LETTERS.

Some System variables


You can see system variables by giving command like $ set, Some of the important System
variables are
System Variable Meaning
BASH=/bin/bash Our shell name
BASH_VERSION=1.14.7(1) Our shell version name
COLUMNS=80 No. of columns for our screen
HOME=/home/vivek Our home directory
9
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

LINES=25 No. of columns for our screen


LOGNAME=students Our logging name
OSTYPE=Linux Our o/s type : -)
PATH=/usr/bin:/sbin:/bin:/usr/sbin Our path settings
PS1=[\u@\h \W]\$ Our prompt settings
PWD=/home/students/Common Our current working directory
SHELL=/bin/bash Our shell name
USERNAME=vivek User name who is currently login to this PC
NOTE that Some of the above settings can be different in your PC. You can print any of the above
variables contain as follows
$ echo $USERNAME
$ echo $HOME
Caution: Do not modify System variable this can some time create problems.

User defined variables (UDV)


To define UDV use following syntax
Syntax: variablename=value
NOTE: Here 'value' is assigned to given 'variablename' and Value must be on right side = sign For
e.g.
$ no=10 # this is ok
$ 10=no # Error, NOT Ok, Value must be on right side of = sign.
To define variable called 'vech' having value Bus
Linux Shell Script Tutorial
http://www.freeos.com/guides/lsst/shellprog.htm (1 of 19) [17/08/2001 17.42.21]
$ vech=Bus
To define variable called n having value 10
$ n=10

Commands Related with Shell Programming

(1)echo [options] [string, variables...]

Displays text or variables value on screen.


Options
-n Do not output the trailing new line.
-e Enable interpretation of the following backslash escaped characters in the strings:
\a alert (bell)
\b backspace
\c suppress trailing new line
\n new line
\r carriage return
10
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

\t horizontal tab
\\ backslash
For eg. $ echo -e "An apple a day keeps away \a\t\tdoctor\n"

(2)More about Quotes


There are three types of quotes
" i.e. Double Quotes
' i.e. Single quotes
` i.e. Back quote
1."Double Quotes" - Anything enclose in double quotes removed meaning of that characters (except
\ and $).
2. 'Single quotes' - Enclosed in single quotes remains unchanged.
3. `Back quote` - To execute command.
For eg.
$ echo "Today is date"
Can't print message with today's date.
$ echo "Today is `date`".
Now it will print today's date as, Today is Tue Jan ....,See the `date` statement uses back quote,
(See also Shell Arithmetic NOTE).

(3) Shell Arithmetic


Use to perform arithmetic operations For e.g.
$ expr 1 + 3
$ expr 2 - 1
$ expr 10 / 2
$ expr 20 % 3 # remainder read as 20 mod 3 and remainder is 2)
$ expr 10 \* 3 # Multiplication use \* not * since its wild card)
$ echo `expr 6 + 3`
For the last statement not the following points
1) First, before expr keyword we used ` (back quote) sign not the (single quote i.e. ') sign. Back
quote is generally found on the key under tilde (~) on PC keyboards OR To the above of TAB key.
2) Second, expr is also end with ` i.e. back quote.
3) Here expr 6 + 3 is evaluated to 9, then echo command prints 9 as sum
4) Here if you use double quote or single quote, it will NOT work, For eg.
$ echo "expr 6 + 3" # It will print expr 6 + 3
$ echo 'expr 6 + 3'

write script to print command ling argument and we will see how to access them

$ cat > demo


11
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

#!/bin/sh
#
# Script that demos, command line args
#
echo "Total number of command line argument are $#"
echo "$0 is script name"
echo "$1 is first argument"
echo $2 is second argument"
echo "All of them are :- $*"

# Script to see whether argument is positive or negative


#
if [ $# -eq 0 ]
then
echo "$0 : You must give/supply one integers"
exit 1
fi
if test $1 -gt 0
then
echo "$1 number is positive"
else
echo "$1 number is negative"
fi

#Script to test for loop


##
if [ $# -eq 0 ]
then
echo "Error - Number missing form command line argument"
echo "Syntax : $0 number"
echo " Use to print multiplication table for given number"
exit 1
fi
n=$1
for i in 1 2 3 4 5 6 7 8 9 10

do
echo "$n * $i = `expr $i \* $n`"
done
Save and Run it as
$ chmod +x mtable
12
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

$ ./mtable 7
$ ./mtable
For first run, Above program print multiplication table of given number where i = 1,2 ... 10 is
multiply by given n (here command line argument 7) in order to produce multiplication table as
7*1=7
7 * 2 = 14
...
..
7 * 10 = 70 And for Second run, it will print message -

#Script to test while statement


##
if [ $# -eq 0 ]
then
echo "Error - Number missing form command line argument"
echo "Syntax : $0 number"
echo " Use to print multiplication table for given number"
exit 1
fi
n=$1
i=1
while [ $i -le 10 ]
do
echo "$n * $i = `expr $i \* $n`"
i=`expr $i + 1`
done
Save it and try as
$ chmod +x nt1
$./nt1 7
Above loop can be explained as follows
n=$1
Set the value of command line argument to variable n. (Here it's set to 7 )
i=1 Set variable i to 1
while [ $i -le 10 ]
This is our loop condition, here if value of i is lessthan 10 then, shell execute all statements between do
and done
do Start loop
echo "$n * $i = `expr $i \* $n`"
13
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Print multiplication table as


7*1=7
7 * 2 = 14
....
7 * 10 = 70, Here each time value of variable n is
multiply be i.
i=`expr $i + 1`
Increment i by 1 and store result to i. ( i.e. i=i+1)
The case Statement
The case statement is good alternative to Multilevel if-then-else-fi statement. It enable you to match
several values against one variable. Its easier to read and write.
Syntax:
case $variable-name in
pattern1) command
...
..
command;;
pattern2) command
Linux Shell Script Tutorial
http://www.freeos.com/guides/lsst/shellprog.htm (16 of 19) [17/08/2001 17.42.21]
...
..
command;;
patternN) command
...
..
command;;
*) command
...
..
command;;
esac
The $variable-name is compared against the patterns until a match is found. The shell then executes all the
statements up to the two semicolons that are next to each other. The default is *) and its executed if no
match is found. For eg.
Conclusion:
In this experiment we learned to write an interactive shell programming and also studied
different commands related with shell programming.

14
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 2 : Write C Program to implement Lexical Analyzer for simple arithmetic operation creates
Output tables (Uniform Symbol table or a. Identifier Table b. Literal Table c. Symbol Table)

TITLE : Lexical Analyzer

AIM : Write C program to implement a lexical analyzer for simple arithmetic operation.

THEORY
Objective:

1. Understand the basic compilation principles.


2. To study lexical analysis phase of compiler.

Compiler takes input as a source program & produces output as an equivalent sequence of machine instruction.
This process consists of two-step processing of source program.
1. Analysis of source program.
2. Synthesis of target program.

Analysis step:

It consist of three sub steps


1. Lexical Analysis - Determine lexical constituents in source program.
2. Syntax Analysis - Determine structure of source string.
3. Semantic Analysis - Determine meaning of source string.

Synthesis Step:

It deals with memory allocation & code generation. The actions in analysis phase are uniquely defined for a given
language. But synthesis step consist of many action instances where action depend on the aspect concerning the
execution environment of the compiler.
e.g. - Operating system interfaces target machine features such as instruction set, addressing modes, etc.

Lexical analysis: The action of scanning the source program into proper syntactic classes is known as lexical
analysis.

Task of Lexical Analysis:

1. To scan the program into basic elements or tokens of the language.


2. To build the Uniform symbol table (table of tokens).
3. To build the inform symbol & literal table.
4. To remove white spaces & comments.
15
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Data structures / Databases required:

1. Source program - Original Source program, which is scanned by compiler as string of characters.
2. Terminal Table - A permanent database that has entry for each terminal symbols such as arithmetic operators,
keyboards, punctuation character such as ‘;’, ‘:’, etc
Fields: Name of the symbol.
3. Literal Table - This table is created during lexical analysis so as to describe all literals in the program.
Fields: Name of the literal.
4. Identifier Table - Created during lexical analysis and describes all identifiers in the program.
Fields: Name of the identifier.
5. Uniform Symbol Table - Created during lexical analysis to represent the program as a string of tokens, rather
than of individual characters. Each uniform symbol contains the identification of the table to which it belongs.(
IDN - Identifier table, LIT - Literal Table TRM - Terminal Symbol Table)and index within that table.
6. Buffer - One buffer or two buffer schemes to load source program part by part to reduce disk i/o.

Sample Input:
A program in C language

Sample Output:
Uniform Symbol Table, Literal Table, Identifier Table.

Code:

#include<stdio.h>
#include<string.h>
void main()
{
char strinput[512]="";
int index;
char identifier[300]="";
char operator[300]="";
char constant[300]="";
int numidentifier=0;
int numoperator=0;
int numconstant=0;
printf("enter the i/p equation\n");
scanf("%s",strinput);
printf("equation you entered is:%s\n",strinput);
for(index=0;index<=strlen(strinput);index++)
16
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
if(isalpha(strinput[index]))
{
identifier[numidentifier++]=strinput[index];
}
else if(isdigit(strinput[index]))
{
constant[numconstant++]=strinput[index];
}
else
{
operator[numoperator++]=strinput[index];
}
}
printf("identifier are ; ");
printf("%s\n",identifier);
printf("operator are ; ");
printf("%s\n",operator);
printf("constant are ; ");
printf("%s\n",constant);
}

Output:

enter the i/p equation


a+b=c-Y
equation you entered is:a+b=c-Y
identifier are ; abcY
operator are ; +=-
constant are ;

CONCLUSION:
Here we studied that the lexical analyzer breaks syntax into a series of tokens and removes any
extra space or comment written in the source code.

17
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 3 : Design of PASS I of two pass assembler for pseudo machine code.

TITLE : Design of PASS I of two pass assembler

AIM : Design of PASS I of two pass assembler for pseudo machine code.

THEORY

A language translator bridges an execution gap to machine language of computer system. An assembler is a
language translator whose source language is assembly language.
Language processing activity consists of two phases, Analysis phase and synthesis phase. Analysis of source
program consists of three components, Lexical rules, syntax rules and semantic rules. Lexical rules govern the
formation of valid statements in source language. Semantic rules associate the formation meaning with valid
statements of language. Synthesis phase is concerned with construction of target language statements, which have
the same meaning as source language statements. This consists of memory allocation and code generation.

Data structures

Pass I Pass II

Intermediate code

Data access
Control transfer

Over view of two pass assembly

Analysis of source program statements may not be immediately followed by synthesis of equivalent target
statements. This is due to forward references issue concerning memory requirements and organization of LP.

18
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Forward reference of a program entity is a reference to the entity, which precedes its definition in the program,
while processing a statement containing a forward reference, language processor does not posses all relevant
information concerning referenced entity. This creates difficulties in synthesizing the equivalent target statements.
This problem can be solved by postponing the generation of target code until more information concerning the
entity is available. This also reduces memory requirements of LP and simplifies its organization. This leads to
multi-pass model of language processing.

Language Processor Pass: -


It is the processing of every statement in a source program or its equivalent representation to perform
language-processing function.

Assembly Language statements: -


There are three types of statements Imperative, Declarative, Assembly directives. An imperative statement
indicates an action to be performed during the execution of assembled program. Each imperative statement usually
translates into one machine instruction. Declarative statement e.g. DS reserves areas of memory and associates
names with them. DC constructs memory word containing constants. Assembler directives instruct the assembler
to perform certain actions during assembly of a program,
e.g. START<constant> directive indicates that the first word of the target program generated by assembler should
be placed at memory word with address <constant>

Function Of Analysis And Synthesis Phase:

Analysis Phase: -
Isolate the label operation code and operand field s of a statement.
Enter the symbol found in label field (if any) and address of next available machine word into symbol table.
Validate the mnemonic operation code by looking it up in the mnemonics table.
Determine the machine storage requirements of the statement by considering the mnemonic operation code and
operand fields of the statement.
Calculate the address of the address of the first machine word following the target code generated for this
statement (Location Counter Processing)

Synthesis Phase:
Obtain the machine operation code corresponding to the mnemonic operation code by searching the mnemonic
table.
Obtain the address of the operand from the symbol table.
Synthesize the machine instruction or the machine form of the constant as the case may be.

Design of a Two Pass Assembler: -


Tasks performed by the passes of two-pass assembler are as follows:

Pass I: -
Separate the symbol, mnemonic opcode and operand fields.
19
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Determine the storage-required foe every assembly language statement and update the location counter.
Build the symbol table.
Construct the intermediate code for every assembly language statement.
Pass II: -
Synthesize the target code by processing the intermediate code generated during

Data structures required for pass I:

1. Source file containing assembly program.


2. OPTAB: A table of mnemonic opcodes and related information.

Mnemonic Class Mnemonic Length


opcode info
MOVER IS (04,1) 1
DS DL R#7
START AD R#11

3. SYMTB: The symbol table.

Symbol Address
Loop 202
Next 214

4. LITTAB: A table of literals used in the program.

Literal Address
= ‘5’
= ‘1’
= ‘1’

5. Intermediate form used Variant 1 / Variant 2


Students are supposed to write the variant used by them.

Data Structure used by Pass II:


1. OPTAB: A table of mnemonic opcodes and related information.
20
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

2. SYMTAB: The symbol table


3. LITTAB: A table of literals used in the program
4. Intermediate code generated by Pass I
5. Output file containing Target code / error listing.

Algorithm/flowchart : Students are supposed to write the algorithm or draw the flowchart.

List of hypothetical instructions:


Instruction Assembly Remarks
Opcode mnemonic

00 STOP stop execution


01 ADD first operand modified condition code set

02 SUB first operand modified condition code set


03 MULT first operand modified condition code set
04 MOVER register memory
05 MOVEM memory register
06 COMP sets condition code
07 BC branch on condition code
08 DIV analogous to SUB
09 READ first operand is not used.
10 PRINT first operand is not used.

Sample Input & Output: -

SAMPLE INPUT FILE SAMPLE OUTPUT FILE


1. START 200
2. MOVER AREG, =’5’ 200 ) + 04 1 211
3. MOVEM AREG , A 201 ) + 05 1 217
4 LOOP MOVER AREG, A 202 ) + 04 1 217
5. MOVER CREG, B 203 ) + 05 3 218
6. ADD CREG, = ‘1’ 204 ) + 01 3 212
……
21
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

12 BC ANY, NEXT 210 ) + 07 6 212


13 LTORG
=’5’ 211 ) + 00 0 005
=’1’ 212 ) + 00 0 001
14 ………
15 NEXT SUB AREG, = ‘1’ 214 ) + 02 1 219
16 BC LT,BACK 215 ) + 07 1 202
17 LAST STOP 216 ) + 00 0 000
18 ORIGIN LOOP + 2
19 MULT CREG, B 204 ) + 03 3 218
20 ORIGIN LAST +1
21 A DS 1 217 )
22 BACK EQU LOOP
23 B DS 1 218 )
24 END
25 =’1’ 219 ) + 00 0 001

Code:
assembler code:
#include<stdio.h>
#include<string.h>

void passone();

struct symbol
{
char sym[10];
int addr;
}S[30];

struct littab
{
char lit[10];
int addr;
}L[30];

char
optab[][6]={"STOP","ADD","SUB","MULT","MOVER","MOVEM","COMP","BC","DIV","READ","PRINT
"};
char regtab[][5]={"AREG","BREG","CREG","DREG"};
char condtab[][4]={"LT","LE","EQ","GT","GE","ANY"};
char adtab[][7]={"START","END","ORIGIN","EQU","LTORG"};

FILE *fs,*ft;
char source[20],buffer[80],tok1[10],tok2[10],tok3[10],tok4[10],tok5[10];
int lc,litcnt=0,poolcnt=0,ec=0,sc=0;

22
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

int pooltab[10];

int search_optab(char *s)


{
int i;
for(i=0;i<11;i++)
{
if(strcmp(optab[i],s)==0)
return i;
}
return (-1);
}

int search_symb(char *s)


{
int i;
for(i=0;i<sc;i++)
{
if(strcmp(S[i].sym,s)==0)
return i;
}
return (-1);

int search_regtab(char *s)


{
int i;
for(i=0;i<4;i++)
{
if(strcmp(regtab[i],s)==0)
return (i+1);
}
return (-1);

int search_condtab(char *s)


{
int i;
for(i=0;i<6;i++)
{
if(strcmp(condtab[i],s)==0)
return (i+1);
}
return (-1);
}

int search_adtab(char *s)


{
int i;
23
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

for(i=0;i<5;i++)
{
if(strcmp(adtab[i],s)==0)
return (i+1);
}
return (-1);

int search_littab(char *s)


{
int i;
for(i=pooltab[poolcnt];i<litcnt;i++)
{
if(strcmp(L[i].lit,s)==0)
return i;
}
return (-1);
}
/*--------------------------------------------------------------------------
*** PASSONE ***
----------------------------------------------------------------------------*/

void passone()
{
int p;
int n,i=0,j=0,k=0;

fs=fopen(source,"r");
if(fs==NULL)
{
printf("\nFILE NOT FOUND");

ft=fopen("ic.txt","w");

while(fgets(buffer,80,fs))
{
n=sscanf(buffer,"%s%s%s%s",tok1,tok2,tok3,tok4);
switch(n)
{
case 1:

i=search_optab(tok1);
if(i==0)
{
fprintf(ft,"(IS, %02d)\n",i);
break;
}

i=search_adtab(tok1);
if(i==2||i==5)
24
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
for(j=pooltab[poolcnt];j<litcnt;j++)
{
L[j].addr=lc++;
}
lc--;
pooltab[++poolcnt]=litcnt;
fprintf(ft,"(AD, %02d)\n",i);
}
break;

case 2:

i=search_adtab(tok1);
if(i==1||i==3)
{
lc=atoi(tok2)-1;
fprintf(ft,"(AD, %02d) (C, %s)\n",i,tok2);
break;
}

i=search_optab(tok1);
if(i==9||i==10)
{
p=search_symb(tok2);
if(p==-1)
{
strcpy(S[sc].sym,tok2);
fprintf(ft,"(IS, %02d) (S, %02d) \n",i,sc);
sc++;
}
else
{
fprintf(ft,"(IS, %02d) (S, %02d)\n",i,p);
}
break;
}

i=search_optab(tok2);
if(i==0)
{
p=search_symb(tok1);
if(p==-1)
{
strcpy(S[sc].sym,tok1);
S[sc].addr=lc;
sc++;
}

else
{
S[p].addr=lc;
}
fprintf(ft,"(IS, %02d)\n",i);
25
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

}
break;

case 3:
i=search_optab(tok1);
if(i>=1 && i<=8)
{
tok2[strlen(tok2)-1]='\0';
if(i==7)
k=search_condtab(tok2);
else
k=search_regtab(tok2);

if(tok3[0]=='=')
{
j=search_littab(tok3);

if(j==-1)
{
strcpy(L[litcnt].lit,tok3);
fprintf(ft,"(IS, %02d) %d (L, %02d) \n",i,k,litcnt);
litcnt++;
}
else
{
fprintf(ft,"(IS, %02d) %d (L, %02d)\n",i,k,j);
}
break;
}
else
{
p=search_symb(tok3);
if(p==-1)
{
strcpy(S[sc].sym,tok3);

fprintf(ft,"(IS, %02d) %d (S, %02d)\n",i,k,sc);


sc++;
}
else
{
fprintf(ft,"(IS, %02d) %d (S, %02d)\n",i,k,p);
}
break;
}
}

if(strcmp(tok2,"DS")==0)
{
p=search_symb(tok1);
if(p==-1)
{
strcpy(S[sc].sym,tok1);
S[sc].addr=lc;

26
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

fprintf(ft,"(DL, 2) (C, %s)\n",tok3);


sc++;
}

else
{
S[p].addr=lc;
fprintf(ft,"(DL, 2) (C, %s)\n",tok3);
}
lc=lc+atoi(tok3)-1;
break;
}

if(strcmp(tok2,"DC")==0)
{
p=search_symb(tok1);
if(p==-1)
{
strcpy(S[sc].sym,tok1);
S[sc].addr=lc;

fprintf(ft,"(DL, 1) (C, %s)\n",tok3);


sc++;
}
else
{
S[p].addr=lc;
fprintf(ft,"(DL, 1) (C, %s)\n",tok3);
}
break;
}
i=search_adtab(tok2);
if(i==4)
{
p=search_symb(tok1);
j=search_symb(tok3);
if(p==-1 && j!=-1)
{
strcpy(S[sc].sym,tok1);
S[sc++].addr=S[j].addr;
}
if(p!=-1 && j==-1)
{
strcpy(S[sc].sym,tok3);
S[sc++].addr=S[p].addr;
}
if(p!=-1 && j!=-1)
{
if(S[j].addr)
S[p].addr=S[j].addr;
else
S[j].addr=S[p].addr;

}
lc--;
27
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

}
break;

case 4:
i=search_optab(tok2);
if(i>=1 && i<=8)
{
p=search_symb(tok1);
if(p==-1)
{
strcpy(S[sc].sym,tok1);
S[sc].addr=lc;
sc++;
}
else
{
S[p].addr=lc;
}
tok3[strlen(tok3)-1]='\0';
if(i==7)
k=search_condtab(tok3);
else
k=search_regtab(tok3);

if(tok4[0]=='=')
{
j=search_littab(tok4);
if(j==-1)
{
strcpy(L[litcnt].lit,tok4);
fprintf(ft,"(IS, %02d) %d
(L, %02d)\n",i,k,litcnt);
litcnt++;
}
else
{
fprintf(ft,"(IS, %02d) %d (L, %02d)\n",i,k,j);
}
}
else
{
p=search_symb(tok4);
if(p==-1)
{
strcpy(S[sc].sym,tok4);
fprintf(ft,"(IS, %02d) %d (S, %02d)\n",i,k,sc);
sc++;
}
else
{
fprintf(ft,"(IS, %02d) %d (S, %02d)\n",i,k,p);

}
}
}
28
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

break;

}
lc++;
}
fcloseall();
}
//---------------------PRINT FILE-----------------------------------------

void print_file(char *target)


{
FILE *fp;
fp=fopen(target,"r");
if(fp==NULL)
{
printf("\n\nERROR");

}
printf("\n\n");
while(fgets(buffer,80,fp))
{
printf("%s",buffer);
}
fclose(fp);
}
//----------------------PRINT LITRAL TABLE--------------------------------
void print_littab()
{
int i;
printf("\n\nLITERAL\t ADDRESS\n");
for(i=0;i<litcnt;i++)
{
printf("\n%s\t%d\n",L[i].lit,L[i].addr);
}
}
//-------------------------PRINT SYMBOL TABLE-------------------------------

void print_symbtab()
{
int p=0;
printf("\n\n SYMBOL \tADDRESS \n");
while(p<sc)
{
printf("\n%s\t%d\n",S[p].sym,S[p].addr);
p=p+1;
}
}
//-------------------------------MAIN FUNCTION-----------------------------

void main()
{

printf("\n\nENTER SOURCE FILE NAME::");


scanf("%s",source);
29
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

printf("\n\nSOURCE CODE::");
print_file(source);

passone();

printf("\n\nLITERAL TABLE::\n");
print_littab();

printf("\n\nSYMBOL TABLE::\n");
print_symbtab();

printf("\n\nINTERMEDIATE CODE::\n");
print_file("ic.txt");

}
//--------------------------END OF PROGRAM-----------------------------------

Ip code:
START 200
MOVER AREG, ='5'
MOVEM AREG, TEMP
MOVER BREG, ='10'
ADD CREG, NEXT
END
TEMP DS 1
NEXT DC '2'
STOP

Ic:
(AD, 01) (C, 200)
(IS, 04) 1 (L, 00)
(IS, 05) 1 (S, 00)
(IS, 04) 2 (L, 01)
(IS, 01) 3 (S, 01)
(AD, 02)
(DL, 2) (C, 1)
(DL, 1) (C, '2')
(IS, 00)

CONCLUSION:
In this experiment we have studied that an assembler is a programme for converting all the
instructions which are written in low-level assembly code into relocatable machine code and
also generating along information for the loader. We also studied about two pass assembler.

30
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 4 : Design of a MACRO PASS-I

TITLE : Macro Processor

AIM : Design of a MACRO PASS-I

THEORY
Macro: Macro allows a sequence of source language code to be defined once and then referred to by name each
time it is to be referred. Each time this name occurs in a program, the sequence of codes is substituted at that
point.
A macro consist of:
1) Name of the macro
2) Set of parameters
3) Body of macro
We can attach a name to a sequence by means of a macro definition, which is formed in following manner:
Start of definition Macro
Macro name mymacro
Macro body ADD AREG,X
ADD BREG,X
End of macro definition MEND

Calling a macro: A macro is called by writing the macro name with actual parameter in an assembly program.
The macro call has following syntax:
<macro name>[<list of parameters>]
Macro expansion:
Each call to a macro is replaced by its body.
Consider a macro named mymacro then the expansion will be as follows:
ADD AREG,X
mymacro ADD BREG,X

Macro parameters:
A macro can have two types of parameters:
1) Positional parameter:
A positional parameter is written as & parameter name.
For example, in the statement
INCR &VARIABLE, &INCR_BY, &USE_REG VARIABLE are positional parameters.

31
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

2) Keyword parameter:
Keyword parameters are used for following purposes.
i) Default value can be assigned to the parameter
ii) During a call to macro, a keyword parameter is specified by its name. It takes the following form:
<parameter name> = <parameter value>

Design of macro processor:


Program with
macro definitions
and calls Macro Target program
Assembler
preprocessor

Assembly language program without macros


Fig.A scheme for a macro pre-processor

Macro pre-processor takes a source program containing macro definitions and macro calls and translates
into an assembly language program without any macro definition or calls. This program can now be handed over
to a conventional assembler to obtain the target language (as shown in figure).
It is possible to implement a macro pre-processor which processes macro definition and macro calls for the
purpose of expansions.
Issues related to the design of a simple macro pre-processor:
i) The macro pre-processor has to perform the four basic tasks:
1) Recognize macro definition
2) Save the macro definition
3) Recognize the macro calls
4) Expand macro calls and substitute arguments
ii) A macro definition is identified by MACRO and MEND pseudo opcodes.
iii) A macro definition is saved as it is required during macro expansion.
iv) A macro call appears as operation mnemonic.
v) During macro expansion, the pre-processor must substitute formal parameters with actual parameters.

Databases used in pass 1:


1) Source program as input.
2) Source program without macro definition as output of pass-1 and input of pass-2
3) Macro Definition Table(MDT)
4) Macro Name Table(MNT)
5) Argument list Array(ALA)
6) Macro Name Table Pointer(MNTP)
7) Macro Definition Table Pointer(MDTP)

32
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

FLOWCHART FOR PASS I:

Start
MDTP=0
MNTP=0
Read next Write copy of
source line source line

Macro Yes go to pass II


pseudo End No
opcode pseudo
Enter Macro opcode
Read next
Yes name and the
source line
current value of
MDTP in MNT Substitute index
MNTP=MNTP+1 notation for
arguments
Prepare Enter the line in
argument List MDT
Enter Macro
name line in MDTP=MDTP+1
MDT YES Yes
MDTP=MDTP+1 MEND No
pseudo
opcode
?

33
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Code:
/*
TITLE:PROGRAM FOR MACRO PROCESSOR PASS-I

*/

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

struct name
{
char nm[20];
char in;
}mnt;

struct vari
{
char var[10];
int cnt;
}v[10];

void main()
{
FILE *f1,*f2,*f3;
char c;
char s[20];
int i=0,k=0,n=0,ch=0,num=1;
char a;

f1=fopen("ip.txt", "r");;
f2=fopen("mdt.txt","w+");
f3=fopen("mnt.txt","w+");
fputs("MACRO NAME Index\n",f3);
while(!feof(f1))
{
i=0;
k=0;
n=0;
num=1;
c=fgetc(f1);
if(isalpha(c)) //if c is from A to Z or a to z
{
//READING THE WORD 'MACRO'
while(c!=' '&&c!='\n'&&c!='\t')
{
s[i]=c;

34
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

c=fgetc(f1);
i++;
}
fputc('\n',f2);

//WRITING LINE NUMBERS


if(c=='\n')
{
fprintf(f2,"%d",ch);
ch++;
fputc(' ',f2);
}
s[i]='\0'; //put terminator after word
k=strcmp(s,"MACRO");

//WRITING 'MACRO' IN OUTPUT FILE


if(k==0)
{
i=0;
while(s[i]!='\0')
{
a=s[i];
fputc(a,f2);
i++;
}
fputc('\n',f2);
i=0;
c=fgetc(f1);

//READING THE NAME OF MACRO


if (isalpha)
{
while(c!=' ')
{
s[i]=c;
c=fgetc(f1);
i++;
}
}
s[i]='\0';

//PREPARING MACRO NAME TABLE


strcpy(mnt.nm,s);
mnt.in=ch;
fputs(mnt.nm,f3);
fputc('\t',f3);
fputc('\t',f3);
fprintf(f3,"%d",ch);
fputc('\n',f3);
fprintf(f2,"%d",ch);
ch++;
fputc(' ',f2);

i=0;
while(s[i]!='\0')
35
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
a=s[i];
fputc(a,f2);
i++;
}
while(c!='&')
{
c=fgetc(f1);
}
i=0;

//TO FIND VARIABLES IN THE MACRO


while(1)
{
if(c=='&')
{
c=fgetc(f1);
while(c!=','&&c!='\n')
{
s[i]=c;
c=fgetc(f1);
i++;
}
}
s[i]='\0';
i=0;
fputc(' ',f2);
fputc('&',f2);
while(s[i]!='\0')
{
a=s[i];
fputc(a,f2);
i++;
}
strcpy(v[n].var,s);
v[n].cnt=num;
num++;
n++;
if(c=='\n')
{
break;
}
c=fgetc(f1);
i=0;
}
while(1)
{
fputc('\n',f2);
c=fgetc(f1);
//TO READ THE MNEMONIC
i=0;
while((c!=' ')&&(c!='\n')&&(c!='\t'))
{
s[i]=c;
c=fgetc(f1);
36
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

i++;
}

//TO WRITE LINE NUMBERS IN OUTPUT FILE


if((c==' ')||(c=='\n'))
{
fprintf(f2,"%d",ch);
ch++;
fputc(' ',f2);
}
s[i]='\0';
i=0;

//WRITING THE MNEMONIC IN OUTPUT FILE


while(s[i]!='\0')
{
a=s[i];
fputc(a,f2);
i++;
}
fputc(' ',f2);
k=strcmp("MEND",s);

//READING INPUT FILE UPTO 'MEND'


if(k==0)
break;
while(c!='\n')
{
while(c!='&')
{
c=fgetc(f1);
}
i=0;
c=fgetc(f1);
while((c!=',')&&(c!='\n'))
{
s[i]=c;
c=fgetc(f1);
i++;
}
s[i]='\0';
for(i=0;i<n;i++)
{
k=strcmp(s,v[i].var);
if(k==0)
{
fprintf(f2,"%d",i+1);
fputc(' ',f2);
break;
}
}
}

}
}
37
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

}
}
fclose(f1);
fclose(f2);
}

Ip:
MACRO
INCR &M1,&M2,&M3
MOV &M1,&M2
ADD &M1,&M3
MOV &M1,&M2
MEND
MACRO
INCR1 &N1,&N2
MOV &N1,&N2
MEND

Mdt:
0 MACRO
1 INCR &M1 &M2 &M3
2 MOV 1 2
3 ADD 1 3
4 MOV 1 2
5 MEND
6 MACRO
7 INCR1 &N1 &N2
8 MOV 1 2
9 MEND

Mnt:
MACRO NAME Index
INCR 1
INCR1 7

Output:

CONCLUSION:
In this experiment we studied about MACRO PROCESSOR PASS-I, for every occurrence of
macro the whole macro body of statements gets expanded in the main source code.

QUESTION:
1) Explain & write MNT MDT for the following program
.
START
INCR #1 #2

38
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

ADD AREG #1
ADD BREG #2
MEND
MAC1 #3
ADD AREG #3
MEND
MOVER AREG A
MAC1 X
MOVER BREG X
INCR Z Y
MOVEM AREG Y
END

2) Explain algorithm for design of macro processor

39
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

40
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 5 : Implement Job scheduling algorithms: FCFS, SJF

AIM : Job scheduling algorithm

OBJECTIVE: Implement job scheduling algorithm:


1. FIFO
2. Shortest path first
3. Round Robin
4. Priority based

THEORY:

1] First in First Out (FIFO):-

It is non preemptive algorithm. Here work load is simply processed in order of arrival.
Implementation of this policy is easily managed by FIFO queue. When the process which is allocated the
resources is at head of queue, then this type of algorithm may result in poor performance.

41
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

By far the simplest CPU scheduling algorithm is the First In First out scheduling algorithm. With this scheme,
the process that requests the CPU first is allocated the CPU first. The implementation of the FIFO policy is
easily managed with a FIFO queue. When a process enters the ready queue, its PCB is linked to the tail of the
queue. When the CPU is free, it is allocated to the process at the head of the queue. The running process is then
removed from the queue. The code for FIFO scheduling is simple to write and understand.
Consider the following set of processes that arrive at time 0, with the length of CPU bust given in milliseconds:
Process Burst Time
P1 24
P2 3
P3 3

If the processes arrive in order p1, p2, p3, and are served in FIFO order, we get the result shown in the
following Gantt chart, which is a bar chart that illustrates a particular schedule, including the start and finish
times of each of the participating process:

P1 P2 P3
0 24 27 30
The waiting time is 0 milliseconds for process p1, 24 milliseconds for p2, and 27 milliseconds
for p3. Thus, the average waiting time is (0+24+27)/3=17 milliseconds. If the processes arrive in the order P2,
P3, P1, however, the result will be as shown in the following Gantt chart:

P2 P3 P1

0 3 6 3
The average waiting time is now (6+0+3)/3=3 milliseconds. This reduction is substantial. Thus, the0average
waiting time under FIFO policy is generally not minimal and may vary substantially if the processes CPU bust
times vary greatly.

2] Shortest Job first Scheduling:-

This algorithm associates with each process the length of the process’s next cpu first. When the CPU is
available, it is assigned to process that has the smallest next CPU burst. If the next CPU bursts of two process’s
are the same, FIFO scheduling is used to break the tie.
The more appropriate term for this scheduling method would be the shortest-next-CPU-burst algorithm, because
scheduling depends on the length of next cpu burst/ process of a processes, rather than the total length. We use
the term SJF because most people and textbooks use this term to refer to this type of scheduling.
As an example of SJF scheduling, consider the following set of the processes, with the length of the burst given
in ms.

Process Burst time


42
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

P1 6
P2 8
P3 7
P4 3
Using SJF scheduling, we would schedule these processes according to the following Gantt Chart:

P4 P1 P3 P2
30

The waiting time is 3ms for process p1, 16 ms for process p2, 9 ms for process p3 and 0ms for process p4.
Thus, the average waiting time is (3+16+9+0)/4=7ms. By comparison, if we were using the FIFO scheduling
scheme, the average rating time would be 10.25ms.

3] Round Robin scheduling:-

The round robin scheduling algorithm designed especially for time scheduling systems. It is similar to FIFO
scheduling, But preemption is added to enable the system to switch between the processed nA small unit of
time, called time Quantum or time slice, is defined. A time slice is generally for 10 to 100 ms. In length. The
ready queue is treated as circular queue. This CPU scheduler goes around the ready queue, allocating the Cpu to
each process for time interval of up to 1 time quantum.
To implement RR scheduling we keep the ready queue as a FIFO queue of process new process are added to the
tail of the ready queue. The cpu scheduler picks the first process from ready queue , steps the timer interrupt
after 1 time quantum, and dispatches the process.
One of two things will then happen. The process may have a cpu burst of less than one time quantum. In this
case the process itself will be released the cpu voluntarily.
The scheduler will then proceed to the next process in the ready queue. Otherwise, if the cpu burst of the
currently running process in the longer than 1 time quantum, the timer will go off and will cause an interrupt to
the operating system. context switch will be executed and the process will be put at the tail of the ready queue.
The cpu scheduler will the select the next process In the ready queue/.
The average waiting time under the RR policy is often long. Consider the following set of process that arrive at
time 0, with the length of the cpu burst given in ms:

Process Burst time


P1 24
P2 3
P3 3
If we use a time quantum of 4 ms, then the process p1 gets the first 4 ms. Since it requires another 20 ms, it is
preempted after the first time quantum, and the cpu is given to the next process in the queue, process p2.
Process p2 does not need 4 ms, so it quits before its time quantum expires. The cpu is then given to the next
43
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

process, process p3. Once each process has received 1 time quantum, the cpu is returned to process p1 for an
additional time quantum the resulting RR schedule is as follows:

0 4 7 10 14 1 22 2 30
P1 P2 P3 P1 P1 8 P1 P1 6 P1

Let’s calculate the average waiting time for the above schedule. P1 waits for 6 milliseconds (10-4),P2 waits for
4 milliseconds ,&P3 waits for 7 milliseconds. Thus, the average waiting time is 17/3=5.66 milliseconds.
In the RR scheduling algorithm, no process is allocated the CPU for for more than 1 time quantum in a row
(unless it is the only runnable process).
Goals of Scheduling:-
1) Fairness:-
A scheduler makes sure each process gets its fair share of CPU & no process can suffer indefinite
post 1.

2) Police Enforcement:-
The scheduler has to make same that system policy is enforced whenever they won’t be able to run.

3) Efficiency:-
Scheduler should keep system busy all time when possible .If the CPU & all i/o devices are kept
running then more work done/sec, if some components are idle.
4) Response Time:-
A scheduler should minimize the turn around time batch user must wait for an o/p.

Code:
fcfs:
#include<stdio.h>
struct job
{
char ch;
int bt;
int pr;
}j[10];
void FCFS(int );
void main()
{
int n,i;
char var='A';
printf("\n Enter No of Process");
scanf("%d",&n);
for(i=0;i<n;i++)

44
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
printf("\n Enter burst time for p[%d]=",i+1);
scanf("%d",&j[i].bt);
j[i].ch=var;
var++;
}
for(i=0;i<n;i++)
{
printf("\n%c %d",j[i].ch,j[i].bt);
}
FCFS(n);
}
void FCFS(int n)
{
int i,k;
int sum=0,s,cnt=1;

for(i=0;i<n;i++)
{
s=0;
for(k=0;k<cnt;k++)
{
s+=j[k].bt;
}
sum+=s;
cnt++;
}

float att=0,awt=0;
att=(float)sum/n;
printf("\nAvarage Turn Around Time %f",att);
sum=sum-s;
awt=(float)sum/n;
printf("\nAvarage Waiting Time =%f",awt);

Output:
Enter No of Process 3

Enter burst time for p[1]= 24

Enter burst time for p[2]=3

Enter burst time for p[3]=3

A 24
B 3
C 3
Avarage Turn Around Time 27.000000
45
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Avarage Waiting Time =17.000000

Sif:
#include<stdio.h>

struct job
{
char ch;
int bt;
int pr;
}j[10];
void SJF(int );
void main()
{
int n,i;
char var='A';
printf("\n Enter No of Process");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\n Enter burst time for p[%d]=",i+1);
scanf("%d",&j[i].bt);
j[i].ch=var;
var++;
}
SJF(n);
}
void SJF(int n)
{
int i,k;
for(i=0;i<n;i++)
{
for(k=i+1;k<n;k++)
{
if(j[i].bt> j[k].bt)
{
struct job temp;
temp=j[i];
j[i]=j[k];
j[k]=temp;
}
}
}

for(i=0;i<n;i++)
{
printf("\n%c %d",j[i].ch,j[i].bt);
}

int sum=0,s,cnt=1;
for( i=0;i<n;i++)
{
s=0;
for(k=0;k<cnt;k++)
46
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
s+=j[k].bt;
}
sum+=s;
cnt++;
}
float att=0,awt=0;
att=(float)sum/n;
printf("\nAvarage Turn Around Time %f",att);
sum=sum-s;
awt=(float)sum/n;
printf("\nAvarage Waiting Time =%f",awt);
}

Output:

Enter No of Process4

Enter burst time for p[1]=2

Enter burst time for p[2]=3

Enter burst time for p[3]=4

Enter burst time for p[4]=5

A 2
B 3
C 4
D 5
1.FCFS
2.SJF
3.exit
Enter Your Choice1

Avarage Turn Around Time 7.500000


Avarage Waiting Time =4.000000

CONCLUSION:

Hence, we have studied various scheduling algorithms.


.

QUESTION:
1) Compare FIFO, shortest job first & round robin algorithm.

47
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

2) What is CPU scheduling & process scheduling?

48
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

49
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

50
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

51
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

52
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

53
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 6 : Implement Bankers Algorithm for deadlock detection and avoidance.

TITLE:- Bankers algorithm

AIM:- Bankers algorithm for deadlock detection and avoidance.

THEORY :-
Deadlocks can occur when processes have been granted exclusive access to devices, files and so forth. To
make the discussion of deadlocks as general as possible, we will refer to the objects granted as resources.
Resources come into two types: preempt able and non-preempt able. A preempt able resources is one that can
be taken away from the process owning it with no ill effects.
A non-preempt able resources, in contrast, is one that cannot be taken away from its current owner without
causing the computation to fail.
The sequence of events required to use resource is given below in an abstract form.
1. Request the resource.
2. Use the resources.
3. Release the resource.
Deadlock can be defined formally as follows:
A set of processes is deadlocked if each process in the set is waiting for an event that only another process in the
set can cause.
Conditions for deadlock :
1. Mutual exclusion condition. Each resource is either currently assigned to exactly one process or is
available.
2. Hold and wait condition. Processes currently holding resources that were granted earlier can request new
resources.
3. No preemtion condition. Resources previously granted cannot be forcibly taken away from the process.
They must be explicitly released by the process holding them.
4. Circular wait condition. There must be circular chain of two or more processes, each of which is waiting
for resource held by the next member of the chain.

Deadlock detection and recovery:


When this technique is used, the system does not do anything except monitor the requests and
releases of resources. Every time a resource is requested or released, the resource graph is updated, and a check
is made to see if any cycles exist. If a cycle exists, one of the processes in the cycle is killed. Detection and
recovery is the strategy often used on large mainframe computers. Care must be taken to restore any modified
files to their original state, however ,and undo any other side effects that may have occurred.

Deadlock avoidance:
We can avoid deadlocks but only if certain information is available in advance.
The Banker's Algorithm for a Single resource:
A scheduling algorithm that can avoid deadlocks is due to Dijkstra and is known as banker's algorithm. It
is modelled on the way a small town banker might deal with a group of customers to whom he has granted lines
of credit. The banker does not necessarily have enough cash on hand to lend every customer the full amount of
each one's line of credit at the same time. In fig. We see four customers A, B, C, D each of whom has been
granted a certain no of credit units. The banker knows that not all customers will need their maximum credit
54
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

immediately, so he has reserved only 10 units rather than 22 units to service them. He also trusts every customer
to be able to repay his loan after receiving his total line of credit, so he knows eventually he can service all the
requests.

A 1 6

B 2 5

C 2 4

D 4 7

Has Max Has Max


A 0 6
0 5
B
C 0 4
D 0 7
Free: 10 free: 2 free: 1
A 1 6

B 1 5

C 2 4

D 4 7

Three resources allocation states: a)safe b)safe c)unsafe.


Each part of the fig shows a state of the system with respect to resource allocation, that is, a list of customers
showing the money already loaned and the maximum credit available. A state is safe if there exists a sequence
of other states that leads to all customers getting loans up to their credit limits (all processes getting all their
resources and terminating).

The banker's Algorithm for Multiple Resources:

55
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

A 3 0 1 1

B 0 1 0 0

C 1 1 1 0
D 1 1 0 1

E 0 0 0 0

A 1 1 0 0
B 0 1 1 2
C 3 1 0 0
D 0 0 1 0
E 2 1 1 0

Resources assigned Resurces needed


E= (6 3 4 2) –Existing resources
P= (5 3 2 2) – Possessed resources
A= (1 0 2 0) – Available resources
We see two matrices. The one on the left shows how many of each resource are currently assigned to each
of the five processes. The matrix on the right shows how many resources each process still needs in order to
complete. As in the single resource case processes must state their total resource needs before executing, so that
the system can compute the right hand matrix at each instant.
The algorithm for checking to see if a state is safe can now be stated
1.Look for a row ,r , whose unmet resource needs are all smaller than or equal to A. If no such row exists,the
systrm will eventually deadlock since no process can run to completion.
2.Assume the process of the row chosen requests all the resources it needs and finishes.Mark that process as
terminated and add all it's resources to the A vector.
3.Repeat steps 1 &2 until either all processes are marked terminated,in which case the initial state was safe, or
until a deadlock occurs,in which case it was not.

Code:

//Banker Algorithm for Deadlock:

#include <stdio.h>
void print(int cm[][10],int am[][10],int av[],int np,int nr)
{ int i,j;
printf("\nMax-claim Allocation Available");
for(i=0;i<np;i++)
{ printf("\n");
for(j=0;j<nr;j++)
printf("%d ",cm[i][j]);
printf(" ");
for(j=0;j<nr;j++)
printf("%d ",am[i][j]);
56
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

printf(" ");
if(i==0)
for(j=0;j<nr;j++)
printf("%d ",av[j]);

}
int canexecute(int cmr[],int amr[],int av[],int nr)
{ int i;
for(i=0;i<nr;i++)
if(cmr[i]-amr[i]> av[i])
return(0);
for(i=0;i<nr;i++)
{ av[i]=av[i]+amr[i];
cmr[i]=amr[i]=0;
}
return(1);
}

int safe(int cm[][10],int am[][10],int av[],int np,int nr)


{ int visited[10],i,flag,count=0;
for(i=0;i<np;i++)
visited[i]=0;
for(;count<np;)
{ for(i=0;i<np ;i++)
if(visited[i]==0 && canexecute(cm[i],am[i],av,nr))
{ count++;
visited[i]=1;
printf("\nNext process=%d",i);
print(cm,am,av,np,nr);
break;
}
if(i==np)
return(0);
}
return(1);
}

void main()
{ static int cm[10][10],am[10][10],rv[10],av[10],cm1[10][10],am1[10][10];
int nr,np,i,j,pno,vector[10];
printf("\nEnter No. of proceses & no. of resources : ");
scanf("%d%d",&np,&nr);
printf("\nEnter claim matrix : ");
for(i=0;i<np;i++)
for(j=0;j<nr;j++)
{ scanf("%d",&cm[i][j]);
cm1[i][j]=cm[i][j];
}
printf("\nEnter allocation matrix : ");
for(i=0;i<np;i++)
for(j=0;j<nr;j++)
{ scanf("%d",&am[i][j]);
am1[i][j]=am[i][j];
57
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

}
printf("\nEnter resource vector : ");
for(i=0;i<nr;i++)
scanf("%d",&rv[i]);
/*calculate available vector */
for(j=0;j<nr;j++)
{ av[j]=rv[j];
for(i=0;i< np;i++)
av[j]-=am[i][j];
}
if(safe(cm,am,av,np,nr))
printf("\n System is in the safe state :\n");
else
printf("\nSysytem not in a safe state");

while(1)
{ for(i=0;i<np;i++)
for(j=0;j<nr;j++)
{ cm[i][j]=cm1[i][j];
am[i][j]=am1[i][j];
}

for(j=0;j<nr;j++)
{ av[j]=rv[j];
for(i=0;i< np;i++)
av[j]-=am[i][j];
}
}

CONCLUSION:-

Hence, we studied banker algorithm for deadlock detection & avoidance.

EXP 7 : Implementation page replacement algorithm: FIFO / LRU


58
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

TITLE : TO IMPLEMENT PAGE REPLACEMENT ALGORITHM

AIM : Implementation of page replacement algorithm


1. FIFO 2. LRU
THEORY :
A virtual memory system is a system where logical address of an instruction or data word is likely to be
different than physical address.
Fundamental approaches used in implementing virtual memory system are :
1. Paging 2. Segmentation

Paging :-
A paging program is virtualized to have signal contiguous address space demonstration of program component
which is performed by architecture of computer system. The demonstration is transport to the program. Thus a
program contained to visualize itself at a single contiguous address space.

Segmentation :-
In segmentation, program identifies a logical entity and declares them as a program component for purpose of
virtual memory implementation.

Pages :-
In paged virtual memory system, the logical address space for a program to be of linear arrangement of fixed size
component is called as pages.

Page Frame :-
The physical memory of a computer system is viewed which consists of page block wherein each one of these is
capable of holding exactly one page of a program.

Page Replacement :-
Page Replacement of a page Pi is done by removing the Pi+1 page from same page block.
The following algorithms are used for the page replacement techniques :
1. FIFO Page Replacement
2. LRO Page Replacement

1. FIFO Page Replacement :-

The simplest page replacement algorithm is a first in first out (FIFO) algorithm.
A FIFO page replacement algorithm associates with each page the time when that page was brought into memory.
When a page has to be replaced, then the oldest place is chosen.

59
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

It is not strictly necessary to record the time when a page is brought in. We can create a FIFO queue to hold all
the pages in the memory. We replace the page at the head of the queue. When a page is brought into memory, we
insert at the tail of the queue.
When the page is up to be used, replace the page which is at the head of the queue when the page is brought in
the memory.
For example :-

7 0 1 2 0 3 0 4 2 3 0 32 1 2 0 1 7 0 1
7

60
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

61
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Here, our three frames are initially empty. The first three references (7, 0, 1) cause page faults and are brought
into these empty frames. The next reference (2) replaces page 7, because page 7 was brought in first. Since 0 is
the next reference and 0 is already in memory, we have no fault for this reference. The first reference to 3 results
in replacement of page 0, since it is now first in the line. Because of this replacement, the next reference, to 0,
will fault. Page 1 is then replaced by page 0. This process continues as shown in the above figure. Every time a
fault occurs, we show which pages are in our three frames. There are fifteen faults altogether.
The FIFO page replacement algorithm is easy to understand and program. However, the performance is not always
good. On one hand, the page replace may be an initialization module that was used a long time ago and is no
longer needed. On other hand, it could contain a heavily used variable that was initialized and is in constant use.
Even if we select for replacement a page that is in active use, everything still works correctly. After we replace
an active page with a new one, a fault occurs almost immediately to retrieve the active page. Some other page
must be replaced to bring the active page back into the memory. Thus, a bad replacement choice increases the
page fault rate and slows process execution. It does not, however, cause incorrect execution.

2. LRU :-

In this method, if we use the recent past as an approximation of the near future, then we can replace the page that
has not been used for the longest period of time. This approach is the least recently used (LRU) algorithm.
LRU replacement associates with each page the time of that page’s last use. When a page must be replaced, LRU
chooses the page that has not been used for the longest period of time. The result of applying LRU to our example
reference string is shown below.

7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
7

62
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

63
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

The LRU algorithm produces twelve faults. When the reference to page 4 occurs, LRU replacement sees that, of
the three frames in the memory, page 2 was used recently. Thus the LRU algorithm replaces page 2, not knowing
that page 2 is about to be used. When it faults for page 2, the LRU algorithm replaces page 3, since it is now the
least recently used of the three pages in the memory.
Despite these problems, LRU replacement with twelve faults is much better than FIFO replacement with fifteen.
The LRU policy is often used as a page replacement algorithm and is considered to be good. The major problem
is how to implement LRU replacement. An LRU page replacement algorithm may require substantial hardware
assistance. The problem is to determine an order for the frames defined by the time of last use. Thus to overcome
this, we use counters or stack.

This replaces the page which is not used for the longest period of time. It associates wit h each page, mostly, with
the page, least used. Result of applying LRO produces 12 faults.

Code:

#include <stdio.h>
#include<stdlib.h>

64
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

void display(int a[],int n)


{
int i;
for (i=0;i<n;i++)
{
if(a[i]>=0)
{
printf("%d",a[i]);
}
}
}
int search(int a[],int frsize,int p)
{
int i;
for(i=0;i<frsize;i++)
{
if(a[i]==p)
{
return(1);
}
}return(0);
}
void fifo(int ref[],int n)
{
int cnt=0,i,j,k,h;
int frame[20],fs;
printf("\nenter size of frame array:");
scanf("%d",&fs);
for(i=0;i<fs;i++)
frame[i]=-1;
k=0;
for(i=0;i<n;i++)
{
printf("\n%d:",ref[i]);
if(search(frame,fs,ref[i])==0)
{
frame[k]=ref[i];
k=(k+1)%fs;
display(frame,fs);
cnt++;
}
}
printf("\n\npage fault=%d",cnt);
h=n-cnt;
printf("\n\npage hits=%d",h);
}
void main()
{
int ref[20],n,ch,i;
printf("\n give size of ref string:");
scanf("%d",&n);
printf("\n give no:");
for(i=0;i<n;i++)
scanf("%d",&ref[i]);
while(1)
65
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

{
printf("\n fifo");
fifo(ref,n);
}
}

CONCLUSION :
So, we have studied different Page Replacement algorithm techniques.
We have also seen and studied the difference between them.

EXP 8 : Case Study: A. Study of System Calls to list files, directories.


TITLE : TO WRITE PROGRAM USING SYSTEM CALL.

AIM : Write a program to list files and directories using system call.
THEORY :
System calls for working with files and directories in Linux
1. Objectives
The current laboratory presents the way to use the most common system calls in order to make input-output
operations on files, as well as operations to handle files and directories in the Linux operating system.
2. File descriptors
The operating system assigns internally to each opened file a descriptor or an identifier (usually this is a
positive integer). When opening or creating a new file the system returns a file descriptor to the process that
executed the call. Each application has its own file descriptors. By convention, the first three file descriptors are
opened at the beginning of each process. The 0 file descriptor identifies the standard input, 1 identifies the
standard output and 2 the standard output for errors. The rest of the descriptors are used by the processes when
opening an ordinary, pipe or special file, or directories. There are five system calls that generate file descriptors:
create, open, fcntl, dup and pipe.
3. System calls when working with files
3.1. System call OPEN
Opening or creating a file can be done using the system call open. The syntax is:
#include <sys/types.h>
#include <sys/stat.h>
66
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

#include <fcntl.h>
int open(const char *path,
int flags,... /* mode_t mod */);
This function returns the file descriptor or in case of an error -1. The number of arguments that this function can
have is two or three. The third argument is used only when creating a new file. When we want to open an existing
file only two arguments are used. The function returns the smallest available file descriptor. This can be used in
the following system calls: read, write, lseek and close. The effective UID or the effective GID of the process that
executes the call has to have read/write rights, based on the value of the argument flags. The file pointer is places
on the first byte in the file. The argument flags is formed by a bitwise OR operation made on the constants defined
in the fcntl.h header.

O_RDONLY
Opens the file for reading.
O_WRONLY
Opens the file for writing.
O_RDWR
The file is opened for reading and writing.
O_APPEND
It writes successively to the end of the file.
O_CREAT
The file is created in case it didn’t already exist.
O_EXCL
If the file exists and O_CREAT is positioned, calling open will fail.
O_NONBLOCK
In the case of pipes and special files, this causes the open system call and any other future I/O operations to never
block.
O_TRUNC
If the file exists all of its content will be deleted.
O_SYNC
It forces to write on the disk with function write. Though it slows down all the system, it can be useful in critical
situations.
The third argument, mod, is a bitwise OR made between a combination of two from the following list:
S_IRUSR, S_IWUSR, S_IXUSR
Owner: read, write, execute.
S_IRGRP, S_IWGRP, S_IXGRP
Group: read, write, execute.
S_IROTH, S_IWOTH, S_IXOTH
Others: read, write, execute.
The above define the access rights for a file and they are defined in the sys/stat.h header.
3.2. System call CREAT
A new file can be created by:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *path, mode_t mod);
The function returns the file descriptor or in case of an error it returns the value -1. This call is equivalent with:
open(path, O_WRONLY | O_CREAT | O_TRUNC, mod);
67
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

The argument path specifies the name of the file, while mod defines the access rights. If the created file doesn’t
exist, a new i-node is allocated and a link is made to this file from the directory it was created in. The owner of
the process that executes the call - given by the effective UID and the effective GUID - must have writing
permission in the directory. The open file will have the access rights that were specified in the second argument
(see umask, too). The call returns the smallest file descriptor available. The file is opened for writing and its initial
size is 0. The access time and the modification time are updated in the i-node. If the file exists (permission to
search the directory is needed), it looses its contents and it will be opened for writing. The ownership and the
access permissions won’t be modified. The second argument is ignored.
3.3. System call READ
When we want to read a certain number of bytes starting from the current position in a file, we use the read
call. The syntax is:
#include <unistd.h>
ssize_t read(int fd, void* buf, size_t noct);

The function returns the number of bytes read, 0 for end of file (EOF) and -1 in case an error occurred. It reads
noct bytes from the open file referred by the fd descriptor and it puts it into a buffer buf. The pointer (current
position) is incremented automatically after a reading that certain amount of bytes. The process that executes a
read operation waits until the system puts the data from the disk into the buffer.
3.4. System call WRITE
For writing a certain number of bytes into a file starting from the current position we use the write call. Its
syntax is:
#include <unistd.h>
size_t write(int fd, const void* buf, size_t noct);
The function returns the number of bytes written and the value -1 in case of an error. It writes noct bytes from
the buffer buf into the file that has as its descriptor fd. It is interesting to note that the actual writing onto the disk
is delayed. This is done at the initiative of the root, without informing the user when it is done. If the process that
did the call or an other process reads the data that haven’t been written on the disk yet, the system reads all this
data out from the cache buffers. The delayed writing is faster, but it has three disadvantages:
a) a disk error or a system error may cause loosing all the data
b) a process that had the initiative of a write operation cannot be informed in case a writing error occurred
c) the physical order of the write operations cannot be controlled.
To eliminate these disadvantages, in some cases the O_SYNC is used. But as this slows down the system and
considering the reliability of today’s systems it is better to use the mechanism which includes using cache buffers.
3.5. System call CLOSE
For closing a file and thus eliminating the assigned descriptor we use the system call close.
#include <unistd.h>
int close(int fd);
The function returns 0 in case of success and -1 in case of an error. At the termination of a process an open file
is closed anyway.

3.6. System call LSEEK


To position a pointer (that points to the current position) in an absolute or relative way can be done by calling
the lseek function. Read and write operations are done relative to the current position in the file. The syntax for
lseek is:
#include <sys/types.h>
68
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

#include <unistd.h>
off_t lseek(int fd, off_t offset, int ref);
The function returns the displacement of the new current position from the beginning of the file or -1 in case of
an error. There isn’t done any I/O operation and the function doesn’t send any commands to the disk controller.
It ref is set to SEEK_SET the positioning is done relative to the beginning of the file (the first byte in the file is
at position 0). If ref is SEEK_CUR the positioning is done relative to the current position. If ref is SEEK_END
then the positioning is done relative to the end of the file. The system calls open, creat, write and read execute an
lseek by default. If a file was opened using the symbolic constant O_APPEND then an lseek call is made to the
end of the file before a write operation.
3.7. System call LINK
To link an existing file to another directory (or to the same directory) link can be used. To make such a link in
fact means to set a new name or a path to an existing file. The link system call creates a hard link. Creating
symbolic links can be done using symlink system call. The syntax of link is:
#include <unistd.h>
int link(const char* oldpath, const char* newpath);
int symlink(const char* oldpath, const char* newpath);
The function returns 0 in case of success and -1 in case of an error. The argument oldpath has to be a path to an
existing file. Only the root has the right to set a link to a directory.
3.8. System call UNLINK
To delete a link (a path) in a directory we can use the unlink system call. Its syntax is:
#include <unistd.h>
int unlink(const char* path);
The function returns 0 in case of success and -1 otherwise. The function decrements the hard link counter in the
i-node and deletes the appropriate directory entry for the file whose link was deleted. If the number of links of a
file becomes 0 then the space occupied by the file and its i-node will be freed. Only the root can delete a directory.
3.9. System calls STAT, LSTAT and FSTAT
In order to obtain more details about a file the following system calls can be used: stat, lstat or fstat.
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char* path, struct stat* buf);
int lstat(const char* path, struct stat* buf);
int fstat(int df, struct stat* buf);
These three functions return 0 in case of success and -1 in case of an error. The first two gets as input parameter
a name of a file and completes the structure of the buffer with additional information read from its i-node. The
fstat function is similar, but it works for files that were already opened and for which the file descriptor is known.
The difference between stat and lstat is that in case of a symbolic link, function stat returns information about the
linked (refered) file, while lstat returns information about the symbolic link file. The struct stat structure is
described in the sys/stat.h header and has the following fields:
struct stat {
mode_t st_mode; /* file type & rights */
ino_t st_ino; /* i-node */
dev_t st_dev; /* număr de dispozitiv (SF) */
nlink_t st_nlink; /* nr of links */
uid_t st_uid; /* owner ID */
gid_t st_gid; /* group ID */
off_t st_size; /* ordinary file size */
time_t st_atime; /* last time it was accessed */
69
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

time_t st_mtime; /* last time it was modified */


time_t st_ctime; /* last time settings were changed */
dev_t st_rdev; /* nr. dispozitiv */
/* pt. fişiere speciale /
long st_blksize; /* optimal size of the I/O block */
long st_blocks; /* nr of 512 byte blocks allocated */
};

The Linux command that the most frequently uses this function is ls. Type declarations for the members of this
structure can be found in the sys/stat.h header. The type and access rights for the file are encrypted in the st_mode
field and can be determined using the following macros:
Table 1. Macros for obtaining the type of a file
Macro Meaning
S_ISREG(st_mode) Regular file.
S_ISDIR(st_mode) Directory file.
S_ISCHR(st_mode) Special device of type character.
S_ISBLK(st_mode) Special device of type block.
S_ISFIFO(st_mode) Pipe file or FIFO.
S_ISLNK(st_mode) Symbolic link.
Decrypting the information contained in the st_mode field can be done by testing the result of a bitwise AND
made between the st_mode field and one of the constants (bit mask): S_IFIFO, S_IFCHR, S_IFBLK, S_IFDIR,
S_IFREG, S_IFLNK, S_ISUID (suid bit set), S_ISGID (sgid bit set), S_ISVTX (sticky bit set), S_IRUSR (read
right for the owner), S_IWUSR (write right for the owner), S_IWUSR (execution right for the owner), etc.
3.10. System call ACCESS
When opening a file with system call open the root verifies the access rights in function of the UID and the
effective GID. There are some cases though when a process verifies these rights based upon the real UID and
GID. A situation when this can be useful is when a process is executed with other access right using the suid or
sgid bit. Even though a process may have root rights during execution, sometimes it is necessary to test whether
the real user can or cannot access the file. For this we can use access which allows verifying the access rights of
a file based on the real UID or GID. The syntax for this system call is:

#include <unistd.h>
int access(const char* path, int mod);
The function returns 0 if the access right exists and -1 otherwise. The argument mod is a bitwise AND between
R_OK (permission to read), W_OK (permission to write), X_OK (execution right), F_OK (the file exists).

3.11. System call UMASK


To enhance the security in case of operations regarding the creation of files, the Linux operating system offers
a default mask to reset some access rights. Encrypting this mask is made in a similar way to the encrypting of
the access rights in the i-node of a file. When creating a file those bits that are set to 1 in the mask invalidate the
corresponding bits in the argument that specify the access rights. The mask doesn’t affect the system call
chmod, so the processes can explicitly set their access rights independently form the umask mask. The syntax
for the call is:
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
70
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

The function returns the value of the previous mask. The effect of the call is shown below:
main() /* test umask */
{
int fd;
umask(022);
if ((fd=creat("temp", 0666))==-1)
perror("creat");
system("ls -l temp");
}
The result will be of the following form:
-rw-r--r-- temp
Note that the write permission for the group and other users beside the owner was automatically reset.
3.12. System call CHMOD
To modify the access rights for an existing file we use:
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char* path, mode_t mod);
The function returns 0 in case of a success and -1 otherwise. The chmod call modifies the access rights of the file
specified by the path depending on the access rights specified by the mod argument. To be able to modify the
access rights the effective UID of the process has to be identical to the owner of the file or the process must have
root rights.
The mod argument can be specified by one of the symbolic constants defined in the sys/stat.h header. Their effect
can be obtained by making a bitwise OR operation on them:
Table 2. Bit masks for testing the access rights of a file
Mode Description
S_ISUID Sets the suid bit.
S_ISGID Sets the sgid bit.
S_ISVTX Sets the sticky bit.
Read, write, execute rights for the owner obtained from:
S_IRWXU
S_IRUSR | S_IWUSR | S_IXUSR
Read, write, execute rights for the group obtained from:
S_IRWXG
S_IRGRP | S_IWGRP | S_IXGRP
Read, write, execute rights for others obtained from:
S_IRWXO
S_IROTH | S_IWOTH | S_IXOTH
3.13. System call CHOWN
This system call is used to modify the owner (UID) and the group (GID) that a certain file belongs to. The
syntax of the function is:
#include <sys/types.h>
#include <unistd.h>
int chown(const char* path, uid_t owner, gid_t grp);
The function returns 0 in case of success and -1 in case of an error. Calling this function will change the owner
and the group of the file specified by the argument path to the values specified by the arguments owner and grp.
None of the users can change the owner of any file (even of his/her own files), except the root user, but they can
change the GID for their own files to that of any group they belong to.
3.14. System call UTIME
There are three members of the structure stat that refer to time. They are
presented in the following table:
71
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Table 3. Timing information associated with a file


Field Description Operation
st_atime Last time the data in the file was accessed Read
st_mtime Last time the data in the file was modified Write
st_ctime Changing the settings for the i-node chmod, chown
The difference between the time the file was last modified and the change in the setting of the i-node is that the
first one refers to the time when the contents of the file were modified while the second one refers to the time
when the information in the i-node was last modified. This is due to the fact that the information in the i-node is
kept separately from the contents of the file. System calls that change the i-node are those ones which modify the
access rights of a file, change the UID, change the number of links, etc. The system doesn’t keep the time when
the i-node was last accessed. This is why neither of the system calls access or stat do not change these times.
The access time and last modification time of any kind of files can be changed by calling one of the system call
presented below:
#include <sys/time.h>
int utimes(const char* path,
const struct timeval* times);
int lutimes(const char* path,
const struct timeval* times);
int futimes(int fd, const struct timeval* times);
The functions return 0 in case of success and -1 otherwise. Only the owner of a file or the root can change the
times associated with a file. The parameter times represents the address (pointer) of a list of two timeval structures,
corresponding to the access and modification time. The fields of the timeval structure are:
struct timeval { long tv_sec; /* seconds passed since 1.01.1970 */
suseconds_t tv_usec; /* microseconds */}
To obtain the current time in the form it is required by the timeval structure, we can use the gettimeofday function.
For different conversions between the normal format of a data and hour and the format specific to the timeval
structure the function ctime can be used or any other functions belonging to the same family (for more details see
the textbook).
4. Functions for working with directories
A directory can be read as a file by anyone whoever has reading permissions for it. Writing a directory as a file
can only be done by the kernel. The structure of the directory appears to the user as a succession of structures
named directory entries. A directory entry contains, among other information, the name of the file and the i-
node of this. For reading the directory entries one after the other we can use the following functions:
#include <sys/types.h>
#include <dirent.h>
DIR* opendir(const char* pathname);
struct dirent* readdir(DIR* dp);
void rewinddir(DIR* dp);
int closedir(DIR* dp);
The opendir function opens a directory. It returns a valid pointer if the opening was successful and NULL
otherwise.
The readdir function, at every call, reads another directory entry from the current directory. The first readdir will
read the first directory entry; the second call will read the next entry and so on. In case of a successful reading the
function will return a valid pointer to a structure of type dirent and NULL otherwise (in case it reached the end
of the directory, for example).
The rewinddir function repositions the file pointer to the first directory entry (the beginning of the directory).
The closedir function closes a previously opened directory. In case of an error it returns the value -1.
72
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

The structure dirent is defined in the dirent.h file. It contains at least two elements:
struct dirent {
ino_t d_fileno; // i-node nr.
char d_name[MAXNAMLEN + 1]; // file name }

CONCLUSION :
Here we have studied system calls in order to make input-output operations on files, as well as
operations to handle files and directories in the Linux operating system

73
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

EXP 9 : Case study: B. Study of System Calls to handle process.

TITLE : TO WRITE PROGRAM USING SYSTEM CALL.

AIM :
THEORY :
System calls for working with files and directories in Linux
1. Objectives
The current laboratory presents the way to use the most common system calls in order to make input -output
operations on files, as well as operations to handle files and directories in the Linux operating system.
2. File descriptors
The operating system assigns internally to each opened file a descriptor or an identifier (usually this is a
positive integer). When opening or creating a new file the system returns a file descriptor to the process that
executed the call. Each application has its own file descriptors. By convention, the first three file descriptors are
opened at the beginning of each process. The 0 file descriptor identifies the standard input, 1 identifies the
standard output and 2 the standard output for errors. The rest of the descriptors are used by the processes when
opening an ordinary, pipe or special file, or directories. There are five system calls that generate file descriptors:
create, open, fcntl, dup and pipe.
3. System calls when working with files
3.1. System call OPEN
Opening or creating a file can be done using the system call open. The syntax is:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path,
int flags,... /* mode_t mod */);
This function returns the file descriptor or in case of an error -1. The number of arguments that this function can
have is two or three. The third argument is used only when creating a new file. When we want to open an exist ing
file only two arguments are used. The function returns the smallest available file descriptor. This can be used in
the following system calls: read, write, lseek and close. The effective UID or the effective GID of the process that
executes the call has to have read/write rights, based on the value of the argument flags. The file pointer is places
on the first byte in the file. The argument flags is formed by a bitwise OR operation made on the constants defined
in the fcntl.h header.

O_RDONLY
Opens the file for reading.
O_WRONLY
Opens the file for writing.
O_RDWR
The file is opened for reading and writing.
O_APPEND
It writes successively to the end of the file.
O_CREAT
74
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

The file is created in case it didn’t already exist.


O_EXCL
If the file exists and O_CREAT is positioned, calling open will fail.
O_NONBLOCK
In the case of pipes and special files, this causes the open system call and any other future I/O operations to never
block.
O_TRUNC
If the file exists all of its content will be deleted.
O_SYNC
It forces to write on the disk with function write. Though it slows down all the system, it can be useful in critical
situations.
The third argument, mod, is a bitwise OR made between a combination of two from the following list:
S_IRUSR, S_IWUSR, S_IXUSR
Owner: read, write, execute.
S_IRGRP, S_IWGRP, S_IXGRP
Group: read, write, execute.
S_IROTH, S_IWOTH, S_IXOTH
Others: read, write, execute.
The above define the access rights for a file and they are defined in the sys/stat.h header.
3.2. System call CREAT
A new file can be created by:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *path, mode_t mod);
The function returns the file descriptor or in case of an error it returns the value -1. This call is equivalent with:
open(path, O_WRONLY | O_CREAT | O_TRUNC, mod);
The argument path specifies the name of the file, while mod defines the access rights. If the created file doesn’t
exist, a new i-node is allocated and a link is made to this file from the directory it was created in. The owner of
the process that executes the call - given by the effective UID and the effective GUID - must have writing
permission in the directory. The open file will have the access rights that were specif ied in the second argument
(see umask, too). The call returns the smallest file descriptor available. The file is opened for writing and its initial
size is 0. The access time and the modification time are updated in the i-node. If the file exists (permission to
search the directory is needed), it looses its contents and it will be opened for writing. The ownership and the
access permissions won’t be modified. The second argument is ignored.
3.3. System call READ
When we want to read a certain number of bytes starting from the current position in a file, we use the read
call. The syntax is:
#include <unistd.h>
ssize_t read(int fd, void* buf, size_t noct);

The function returns the number of bytes read, 0 for end of file (EOF) and -1 in case an error occurred. It reads
noct bytes from the open file referred by the fd descriptor and it puts it into a buffer buf. The pointer (current
position) is incremented automatically after a reading that certain amount of bytes. The process that executes a
read operation waits until the system puts the data from the disk into the buffer.
3.4. System call WRITE

75
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

For writing a certain number of bytes into a file starting from the current position we use the write call. Its
syntax is:
#include <unistd.h>
size_t write(int fd, const void* buf, size_t noct);
The function returns the number of bytes written and the value -1 in case of an error. It writes noct bytes from
the buffer buf into the file that has as its descriptor fd. It is interesting to note that the actual writing onto the disk
is delayed. This is done at the initiative of the root, without informing the user when it is done. If the process that
did the call or an other process reads the data that haven’t been written on the disk yet, the system reads all this
data out from the cache buffers. The delayed writing is faster, but it has three disadvantages:
a) a disk error or a system error may cause loosing all the data
b) a process that had the initiative of a write operation cannot be informed in case a writing error occurred
c) the physical order of the write operations cannot be controlled.
To eliminate these disadvantages, in some cases the O_SYNC is used. But as this slows down the system and
considering the reliability of today’s systems it is better to use the mechanism which includes using cache buffers.
3.5. System call CLOSE
For closing a file and thus eliminating the assigned descriptor we use the system call close.
#include <unistd.h>
int close(int fd);
The function returns 0 in case of success and -1 in case of an error. At the termination of a process an open file
is closed anyway.

3.6. System call LSEEK


To position a pointer (that points to the current position) in an absolute or relative way can be done by calling
the lseek function. Read and write operations are done relative to the current position in the file. The syntax for
lseek is:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int ref);
The function returns the displacement of the new current position from the beginning of the file or -1 in case of
an error. There isn’t done any I/O operation and the function doesn’t send any commands to the disk controller.
It ref is set to SEEK_SET the positioning is done relative to the beginning of the file (the first byte in the file is
at position 0). If ref is SEEK_CUR the positioning is done relative to the current position. If ref is SEEK_END
then the positioning is done relative to the end of the file. The system calls open, creat, write and read execute an
lseek by default. If a file was opened using the symbolic constant O_APPEND then an lseek call is made to the
end of the file before a write operation.
3.7. System call LINK
To link an existing file to another directory (or to the same directory) link can be used. To make such a link in
fact means to set a new name or a path to an existing file. The link system call creates a hard link. Creating
symbolic links can be done using symlink system call. The syntax of link is:
#include <unistd.h>
int link(const char* oldpath, const char* newpath);
int symlink(const char* oldpath, const char* newpath);
The function returns 0 in case of success and -1 in case of an error. The argument oldpath has to be a path to an
existing file. Only the root has the right to set a link to a directory.
3.8. System call UNLINK
76
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

To delete a link (a path) in a directory we can use the unlink system call. Its syntax is:
#include <unistd.h>
int unlink(const char* path);
The function returns 0 in case of success and -1 otherwise. The function decrements the hard link counter in the
i-node and deletes the appropriate directory entry for the file whose link was deleted. If the number of links of a
file becomes 0 then the space occupied by the file and its i-node will be freed. Only the root can delete a directory.
3.9. System calls STAT, LSTAT and FSTAT
In order to obtain more details about a file the following system calls can be used: stat, lstat or fstat.
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char* path, struct stat* buf);
int lstat(const char* path, struct stat* buf);
int fstat(int df, struct stat* buf);
These three functions return 0 in case of success and -1 in case of an error. The first two gets as input parameter
a name of a file and completes the structure of the buffer with additional information read from its i-node. The
fstat function is similar, but it works for files that were already opened and for which the file descriptor is known.
The difference between stat and lstat is that in case of a symbolic link, function stat returns information about the
linked (refered) file, while lstat returns information about the symbolic link file. The struct stat structure is
described in the sys/stat.h header and has the following fields:
struct stat {
mode_t st_mode; /* file type & rights */
ino_t st_ino; /* i-node */
dev_t st_dev; /* număr de dispozitiv (SF) */
nlink_t st_nlink; /* nr of links */
uid_t st_uid; /* owner ID */
gid_t st_gid; /* group ID */
off_t st_size; /* ordinary file size */
time_t st_atime; /* last time it was accessed */
time_t st_mtime; /* last time it was modified */
time_t st_ctime; /* last time settings were changed */
dev_t st_rdev; /* nr. dispozitiv */
/* pt. fişiere speciale /
long st_blksize; /* optimal size of the I/O block */
long st_blocks; /* nr of 512 byte blocks allocated */
};

The Linux command that the most frequently uses this function is ls. Type declarations for the members of this
structure can be found in the sys/stat.h header. The type and access rights for the file are encrypted in the st_mode
field and can be determined using the following macros:
Table 1. Macros for obtaining the type of a file
Macro Meaning
S_ISREG(st_mode) Regular file.
S_ISDIR(st_mode) Directory file.
S_ISCHR(st_mode) Special device of type character.
S_ISBLK(st_mode) Special device of type block.
S_ISFIFO(st_mode) Pipe file or FIFO.
S_ISLNK(st_mode) Symbolic link.
77
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

Decrypting the information contained in the st_mode field can be done by testing the result of a bitwise AND
made between the st_mode field and one of the constants (bit mask): S_IFIFO, S_IFCHR, S_IFBLK, S_IFDIR,
S_IFREG, S_IFLNK, S_ISUID (suid bit set), S_ISGID (sgid bit set), S_ISVTX (sticky bit set), S_IRUSR (read
right for the owner), S_IWUSR (write right for the owner), S_IWUSR (execution right for the owner), etc.
3.10. System call ACCESS
When opening a file with system call open the root verifies the access rights in function of the UID and the
effective GID. There are some cases though when a process verifies these rights based upon the real UID and
GID. A situation when this can be useful is when a process is executed with other access right using the suid or
sgid bit. Even though a process may have root rights during execution, sometimes it is necessary to test whether
the real user can or cannot access the file. For this we can use access which allows verifying the access rights of
a file based on the real UID or GID. The syntax for this system call is:

#include <unistd.h>
int access(const char* path, int mod);
The function returns 0 if the access right exists and -1 otherwise. The argument mod is a bitwise AND between
R_OK (permission to read), W_OK (permission to write), X_OK (execution right), F_OK (the file exists).

3.11. System call UMASK


To enhance the security in case of operations regarding the creation of files, the Linux operating system offers
a default mask to reset some access rights. Encrypting this mask is made in a similar way to the encrypting of
the access rights in the i-node of a file. When creating a file those bits that are set to 1 in the mask invalidate the
corresponding bits in the argument that specify the access rights. The mask doesn’t affect the system call
chmod, so the processes can explicitly set their access rights independently form the umask mask. The syntax
for the call is:
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
The function returns the value of the previous mask. The effect of the call is shown below:
main() /* test umask */
{
int fd;
umask(022);
if ((fd=creat("temp", 0666))==-1)
perror("creat");
system("ls -l temp");
}
The result will be of the following form:
-rw-r--r-- temp
Note that the write permission for the group and other users beside the owner was automatically reset.
3.12. System call CHMOD
To modify the access rights for an existing file we use:
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char* path, mode_t mod);
The function returns 0 in case of a success and -1 otherwise. The chmod call modifies the access rights of the file
specified by the path depending on the access rights specified by the mod argument. To be able to modify the
78
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

access rights the effective UID of the process has to be identical to the owner of the file or the process must have
root rights.
The mod argument can be specified by one of the symbolic constants defined in the sys/stat.h header. Their effect
can be obtained by making a bitwise OR operation on them:
Table 2. Bit masks for testing the access rights of a file
Mode Description
S_ISUID Sets the suid bit.
S_ISGID Sets the sgid bit.
S_ISVTX Sets the sticky bit.
Read, write, execute rights for the owner obtained from:
S_IRWXU
S_IRUSR | S_IWUSR | S_IXUSR
Read, write, execute rights for the group obtained from:
S_IRWXG
S_IRGRP | S_IWGRP | S_IXGRP
Read, write, execute rights for others obtained from:
S_IRWXO
S_IROTH | S_IWOTH | S_IXOTH
3.13. System call CHOWN
This system call is used to modify the owner (UID) and the group (GID) that a certain file belongs to. The
syntax of the function is:
#include <sys/types.h>
#include <unistd.h>
int chown(const char* path, uid_t owner, gid_t grp);
The function returns 0 in case of success and -1 in case of an error. Calling this function will change the owner
and the group of the file specified by the argument path to the values specified by the arguments owner and grp.
None of the users can change the owner of any file (even of his/her own files), except the root user, but they can
change the GID for their own files to that of any group they belong to.
3.14. System call UTIME
There are three members of the structure stat that refer to time. They are
presented in the following table:
Table 3. Timing information associated with a file
Field Description Operation
st_atime Last time the data in the file was accessed Read
st_mtime Last time the data in the file was modified Write
st_ctime Changing the settings for the i-node chmod, chown
The difference between the time the file was last modified and the change in the setting of the i-node is that the
first one refers to the time when the contents of the file were modified while the second one refers to the time
when the information in the i-node was last modified. This is due to the fact that the information in the i-node is
kept separately from the contents of the file. System calls that change the i-node are those ones which modify the
access rights of a file, change the UID, change the number of links, etc. The system doesn’t keep the time when
the i-node was last accessed. This is why neither of the system calls access or stat do not change these times.
The access time and last modification time of any kind of files can be changed by calling one of the system call
presented below:
#include <sys/time.h>
int utimes(const char* path,
const struct timeval* times);
int lutimes(const char* path,
const struct timeval* times);

79
TE E&TC (SEM II)
SPOS
DYPIEMR, Akurdi. Department of E&TC

int futimes(int fd, const struct timeval* times);


The functions return 0 in case of success and -1 otherwise. Only the owner of a file or the root can change the
times associated with a file. The parameter times represents the address (pointer) of a list of two timeval structures,
corresponding to the access and modification time. The fields of the timeval structure are:
struct timeval { long tv_sec; /* seconds passed since 1.01.1970 */
suseconds_t tv_usec; /* microseconds */}
To obtain the current time in the form it is required by the timeval structure, we can use the gettimeofday function.
For different conversions between the normal format of a data and hour and the format specific to the timeval
structure the function ctime can be used or any other functions belonging to the same family (for more details see
the textbook).
4. Functions for working with directories
A directory can be read as a file by anyone whoever has reading permissions for it. Writing a directory as a file
can only be done by the kernel. The structure of the directory appears to the user as a succession of structures
named directory entries. A directory entry contains, among other information, the name of the file and the i-
node of this. For reading the directory entries one after the other we can use the following functions:
#include <sys/types.h>
#include <dirent.h>
DIR* opendir(const char* pathname);
struct dirent* readdir(DIR* dp);
void rewinddir(DIR* dp);
int closedir(DIR* dp);
The opendir function opens a directory. It returns a valid pointer if the opening was successful and NULL
otherwise.
The readdir function, at every call, reads another directory entry from the current directory. The first readdir will
read the first directory entry; the second call will read the next entry and so on. In case of a successful reading the
function will return a valid pointer to a structure of type dirent and NULL otherwise (in case it reached the end
of the directory, for example).
The rewinddir function repositions the file pointer to the first directory entry (the beginning of the directory).
The closedir function closes a previously opened directory. In case of an error it returns the value -1.
The structure dirent is defined in the dirent.h file. It contains at least two elements:
struct dirent {
ino_t d_fileno; // i-node nr.
char d_name[MAXNAMLEN + 1]; // file name }

CONCLUSION :
Here we have studied system calls to handle process in which we have studied about process
control, file management, device management, information maintenance and
communication

80
TE E&TC (SEM II)
SPOS

You might also like