1 Shell Programming 21-07-2025
1 Shell Programming 21-07-2025
List of Experiments
Aim: To learn and understand the syntax of basic Linux commands and file systems
commands
Description:
Syntax
$ pwd
2) cal command
$ cal
cal ’ will display calendar for the specified month and year.
3) echo command
$echo
The value of a variable precede the variable with a $ sign. Variable example is ‘HOME’.
$ echo $HOME
4) date command
$ date
5) tty command
$ tty
1
Displays current terminal.
6) whoami command
$ whoami
7) id command
This command prints user and groups (UID and GID) of the current user.
$ id
8) clear command
9) whatis command
It provides one line description about the command. It can be used as a quick reference for
any command.
$ whatis date
$ cd [path-to-directory]
Change the current working directory to the directory provided as argument. If no argument
is given to ‘cd’, it changes the directory to the user's home directory. The directory path can
be an absolute path or relative to current directory. The absolute path always starts with /. The
current directory can be checked with ‘pwd’ command.
$ ls [files-or-directories]
List files and/or directories. If no argument is given, the contents of current directory are
shown.
$ ls
If a directory is given as an argument, files and directories in that directory are shown.
$ ls /usr
2
bin games include lib lib64 local sbin share src
a) Copy command
$cp source destination
b) move command
$ mv source destination
c) To remove or Delete
$ rmdir
'rmdir' command removes any empty directories, but cannot delete a directory if a file
is present in it.
1) file command
The file command determines the file type of a given file.
2) stat command
To check the status of a file. This provides more detailed information about a file.
3) cat command
The 'cat' command is actually a concatenator but can be used to view the contents of a
file.
4) head command
Displays the first few lines of a file. By default, the ‘head’ command displays the first
10 lines of a file.
5) tail command
Similar to ‘head’; the ‘tail’ command shows the last 10 lines by default, and -n option
is available as well
6) wc command
Word count
This command counts lines, words and letters of the input given to it.
3
Exp. No: 02 Shell script Programming
Objective: To understand the concept of shell and write the C program using shell script.
Description:
Shell
The shell is the command prompt within Linux where we can type commands. If
we have logged into a machine over a network (using ssh or telnet) then the
commands you entered were run by the shell. If you are logged in using a
graphical interface then you will may need to open a terminal client to see the
shell. There are several different terminal clients available such as xterm, konsole
and lxterm, or it may be just named Terminal Emulator.
Windows users may be familiar with the concept of a command prompt, or DOS
prompt, which looks similar to a UNIX/Linux shell. The UNIX shell has more
features and is practically an entire programming language, although doesn’t let
that put you off as you can use the shell without any programming ability.
To take a basic view of how Linux is built up see the diagram below:
The kernel is the heart of the operating system. This is the bit that is
actually Linux. The kernel is a process that runs continuously managing the
computer.
The shell is an application that allows users to communicate with the computer. It
is a text based application that allows programs to be started and tasks to be run.
The shell is within a collection of utilities known as GNU. Without the kernel the
computer cannot run and without the GNU utilities it can't do anything useful
which is why the operating system is sometimes called GNU/Linux;
Name of Command
Description
shell name
4
Bourne The most basic shell available on all
Sh
shell UNIX systems
Korn Based on the Bourne shell with
ksh / pdksh
Shell enhancements
Similar to the C programming
C Shell Csh
language in syntax
Bourne Again Shell combines the
Bash advantages of the Korn Shell and the
Bash
Shell C Shell. The default on most Linux
distributions.
Tcsh Tcsh Similar to the C Shell
When you login to a Linux machine (or open a shell window) you will normally
be in the bash shell.
You can change shell temporarily by running the appropriate shell command. To
change your shell for future logins then you can use the chsh command. This is
normally setup to only allow you to change to one of the approved shells listed in
the /etc/shells file. If you change your shell for future sessions this is stored in
the /etc/passwd file.
The shell is more than just a way of typing commands. It can be used to stop,
start, suspend programs and by writing script files it becomes a programming
language in itself.
When logged into the shell you will normal see one of the following prompts: $,
% or #. This is an indication that the shell is waiting for an input from the user.
The Bourne, Korn, and Bash shells all use a similar syntax. If however you are in
the C or tcsh shells this uses a completely different syntax and can require
commands to be entered differently. To make it a little easier these have two
different prompts depending upon the shell.
echo $0
The vi Editor
Vi standard UNIX "visual" editor
Syntax: $ vi file ...
Parameters:
1. If file doesn’t exist, vi will create it
2. Derived from command-drive editors (ed and ex).
3. Uses temporary storage called an editing buffer
5
vi is always in one of two modes
Vi Commands
Esc Go to command mode
Vi Scope
^G Show the line number on the mode line
n key-stroke(s) Repeat the key-stroke(s) n number of times
uUndo last change U Undoes all changes on the current line
eForward to the end of the current word b Backward to the beginning of the current
word
$ Forward to the end of the line 0 Backward to the beginning of the line
) Forward to the beginning of the next sentence ( Backward to the beginning of the current
sentence
} Forward to the beginning of the next paragraph { Backward to the beginning of the current
paragraph
Moving the Cursor
kUp one line j Down one line
lForward a character h Back one character b Back one word
oBeginning of the line $ End of the line
^D Half a page down ^U Half a page up
^FFull page down ^B Full page up
G End of buffer nG Go to line n 1G Beginning of the buffer
Entering Insert mode
aInsert after cursor A Insert at the end of the line
iInsert before the cursor o Insert a blank line
rReplace a single character R Enter text in overwrite mode
Killing, copying and pasting
xDelete character after cursor dd Kill current line
dscope Kill the scope j Close up lines
yyYank a line (copy) y scope Yank the scope
pPaste the kill buffer after the cursor p Paste the kill buffer before the cursor
Rearranging Text :
To Rearrange text using vi:– Yank or delete the text.
Move the cursor to where the text should go.
Place the yanked or deleted text there.
Examples What it does
ywYanks a word y$ Yanks to the end of the line
yy or Y Yanks the current line j Close up lines
yyYank a line (copy) 3yw Yanks three words
3Y Yanks three lines, starting with the current line
Searching and Replacing
/textstring Searches for textstring / Searches again for the same textstring
?textstring Searches backwards for textstring n Searches again (forwards or backwards)
N Reverses the direction of the search
date
The if-then StatementThe Bourne shell also has an if-then construct. The syntax of the
construct is as follows:
if command_1
then command_2
command_3
fi
command_4
7
then
echo file copied successfully
fi
In the program 1, the echo command is executed only if the cp command is successful.
The if-then-else Statement executes one set of commands if a condition is true and a
different set of commands if the condition is false.
if command_1
then
command_2
command_3
else
command_4
command_5
fi
if cp $1 $2
then
echo file copied successfully
else
echo failed to copy the file
fi
The testcommand examines some condition and returns a zero exit status if the condition is
true and a nonzero exit status if the condition is false.
The conditions that can be tested fall into four categories: 1) String operators that test the
condition or relationship of character strings; 2) Integer relationships that test the numerical
relationship of two integers; 3) File operators that test for the existence or state of a file; 4)
Logical operators that allow for and/or combinations of the other conditions.
8
int1 -ne int2 True if int1 is not equal to int2
int1 -gt int2 True if int1 is greater than int2
int1 -ge int2 True if int1 is greater than or equal to int2
int1 -lt int2 True if int1 is less than int2
int1 -le int2 True if int1 is less than or equal to int2
9
Program – 3 :Demonstrates the use of test command
# if basic is less than 1500, then HRA=10% DA=90%
# if his salary is either equal to or above 1500 then HRA = 500 DA 98%
# Find the gross salary of the employee
echo -e "Enter basic salary : \c"
read sal
if [ $sal -lt 1500 ]
then
hra = $sal \* 10/100 | bc
da = $sal \* 90/100 | bc
echo hra
echo da
fi
10
The case Statement The case statement is cleaner because it does away with the elifs and the
thens. It is more powerful because it allows pattern matching, much as the command-line
interpreter does. The case statement allows a value to be named, which is almost always a
variable, and a series of patterns to be used to match against the value, and a series of
commands to executed if the value matches the pattern. The general syntax of case is as
follows:
case value in
pattern1)
command
command ;;
...
patternn)
command;
esac
The case statement executes only one set of commands. If the value matches more than one
of the patterns, only the first set of commands specified is executed. The double semicolons
after a command act as the delimiter of the commands to be executed for a particular pattern
match.
The Bourne shell has three different looping constructs built into the language.The three
types of loops are the while loop, the until loop, and the for loop;
while Loop The while construct enables you to specify commands that will be executed
while some condition is true.The general format:
while command
do
command
command
...
command
done
11
Program - 6 prints the square of integers in succession
int=1
while [ $int -lt 5 ]
do
sq='expr $int \* $int'
echo $sq
int='expr $int + 1'
done
echo "Job Complete"
until Loop The while construct causes the program to loop as long as some condition is true.
The until construct is the complement to while; it causes the program to loop until a condition
is true. The general format of the until construct is as follows:
until command
do
command
command
...
command
done
Processing an Arbitrary Number of Parameters with shiftBefore considering the for loop,
it would be helpful to look at the shift command, since the for loop is really a shorthand use
of shift.
Program – 7 shifter
until [ $# -eq 0 ]
do
echo "Argument is $1 and 'expr $# - 1' argument(s) remain"
shift
done
if [ $# -eq 0 ]
then
echo "Usage: sumints integer list"
exit 1
12
fi
sum=0
until [ $# -eq 0 ]
do
sum=´´expr $sum + $1´´
shift
done
echo $sum
for Loop for each word in the argument list it has been supplied. For each iteration of the
loop, a variable name supplied on the for command line assumes the value of the next word
in the argument list. The general syntax of the for loop is as follows:
for variable in arg1 arg2 ... argn
do
command
...
command
done
Program11:
AIM:Write a shellscript to print the multiplication table for the given number.
13
echo “enter the number”
read n
for i in 1 2 3 4 5 6 7 8 9 10
do
x= `expr $n \* $i`
echo “ $n * $i = $x”
done
Input:
enter the number6
Output:
6*1=6
6*2=12
6*3=18
6*4=24
6*5=30
6*6=36
6*7=42
6*8=48
6*9=54
6*10=60
Program 12:
AIM:Write a shell script to perform simple calculator.
14
Exp. No: 03 Creation of child process using fork system call
Description
Child Process
A child process is the creation of a parent process, which can be defined as the main
process that creates child or sub processes to perform certain operations.
Each process can have many child processes but only one parent. A child process
inherits most of its parent's attributes.
System call fork () is used to create processes. It takes no arguments and returns a
process ID. The purpose of fork () is to create a new process, which becomes the child
process of the caller.
After a new child process is created, both processes will execute the next instruction
following the fork () system call. Therefore, we have to distinguish the parent from the child.
This can be done by testing the returned value of fork ():
If fork () returns a negative value, the creation of a child process was unsuccessful.
fork () returns a positive value, the process ID of the child process, to the parent.
The returned process ID is of type pid_t defined in sys/types.h. Normally, the process ID is
an integer. Moreover, a process can use function getpid() to retrieve the process ID assigned
to this process.
Therefore, after the system call to fork (), a simple test can tell which process is the child.
Procedure:
15
int main(void)
{
printf("Hello \n");
fork();
printf("bye\n");
return 0;
}
Program 2: Fork PID
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
pid_t pid, ppid;
Program 3:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t c_pid;
c_pid = fork(); //duplicate
if( c_pid == 0 ){
//child: The return of fork() is zero
printf("Child: I'm the child: %d\n", c_pid);
16
}else{
//error: The return of fork() is negative
perror("fork failed");
_exit(2); //exit failure, hard
return 0; //success
}
Program 4: Example of multiple activities PARENT AND CHILD processes
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#define BUFLEN 10
int main(void)
{
int i;
char buffer[BUFLEN+1];
pid_t fork_return;
fork_return = fork( );
if (fork_return == 0)
{
strncpy(buffer, "CHILD\n", BUFLEN); /*in the child process*/
buffer[BUFLEN] = '\0';
}
else if(fork_return > 0)
{
strncpy(buffer, "PARENT\n", BUFLEN); /*in the parent process*/
buffer[BUFLEN] = '\0';
}
else if(fork_return == -1)
{
printf("ERROR:\n");
switch (errno)
{
case EAGAIN:
printf("Cannot fork process: System Process Limit Reached\n");
case ENOMEM:
17
printf("Cannot fork process: Out of memory\n");
}
return 1;
}
for (i=0; i<5; ++i) /*both processes do this*/
{
sleep(1); /*5 times each*/
write(1, buffer, strlen(buffer));
}
return 0;
}
#include <sys/types.h>
#include <sys/wait.h>
c_pid = fork();
18
if (c_pid == 0){
/* CHILD */
//execute ls
execvp( ls_args[0], ls_args);
//only get here if exec failed
perror("execve failed");
}else if (c_pid > 0){
/* PARENT */
printf("Parent: finished\n");
}else{
perror("fork failed");
_exit(1);
}
19
// Name of program argv array
// is ls_args[0] for ls_args
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int p[2];
pid_t pid;
char inbuf[10],outbuf[10];
20
if(pipe(p)==-1)
{
printf("pipe failed\n");
return 1;
}
else
printf(" pipe created\n");
if((pid=fork()))
{
printf("In parent process\n");
printf("type the data to be sent to child");
scanf("%s",outbuf);
write (p[1],outbuf,10);
sleep(2);
printf("after sleep in parent process\n");
}
else
{
printf("In child process\n");
read(p[0],inbuf,10);
printf("the data received by the child is %s\n",inbuf);
sleep(2);
printf("After sleep in child\n");
}
return 0;
}
Output
Objective:
1. To write a C program to implement the CPU scheduling algorithm for FIRST COME
FIRST SERVE.
FCFS:
CPU scheduler will decide which process should be given the CPU for its execution. For this
it use different algorithm to choose among the process. One among that algorithm is FCFS
algorithm.
In this algorithm the process which arrives first is given the cpu after finishing its request
only it will allow CPU to execute other process.
SJF:
This algorithm associates with each process the length of the process's next CPU burst.
When the CPU is available, it is assigned to the process that has the smallest next CPU burst.
If the next CPU bursts of two processes are the same, FCFS scheduling is used.
RR :
The round-robin (RR) scheduling algorithm is designed especially for time-sharing systems.
It is similar to FCFS scheduling. A small unit of time, called a time quantum or time slice, is
defined. A time quantum is generally from 10 to 100 milliseconds. The ready queue is treated
as a circular queue.
Procedure:
#include<stdio.h>
#include<unistd.h>
struct Sched
{
int arrv_tym;
int priority;
int svc_tym;
int wait_tym;
int status;
}s[5];
int Fcfs();
int SJf();
int Priority();
int Fcfs()
22
{
int i,wait_tym=0,clock=s[0].arrv_tym;
for(i=0;i<5;i++)
{
wait_tym=wait_tym+(clock-s[i].arrv_tym);
clock=clock+s[i].svc_tym;
s[i].status=1;
}
return wait_tym;
}
int Sjf()
{
int i,wait_tym=0,n=4;
int clock=s[0].svc_tym;
int chosen=1,svc_tym=100;
s[0].status=1;
for(i=1;i<5;i++)
{
s[i].status=0;
}
printf("\nOrder is::\n Job Num:1");
while(n>0)
{
for(i=1;i<5;i++)
{
if((s[i].arrv_tym<=clock)&&(s[i].svc_tym<=svc_tym)&&(s[i].status==0))
{
chosen=i;
svc_tym=s[chosen].svc_tym;
}
}
printf("\n Job Num:%d ",(chosen+1));
s[chosen].status=1;
wait_tym=wait_tym+(clock-s[chosen].arrv_tym) ;
clock=clock+s[chosen].svc_tym;
svc_tym=100;
n--;
}
return wait_tym;
}
int Priority()
{
int i,wait_tym=0,n=4;
int clock=s[0].svc_tym;
int chosen=1,priority=100;
s[0].status=1;
for(i=1;i<5;i++)
{
s[i].status=0;
}
23
printf("\nOrder is::\n Job Num:1");
while(n>0)
{
for(i=1;i<5;i++)
{
if((s[i].arrv_tym<=clock)&&(s[i].status==0)&&(s[i].priority<=priority))
{
chosen=i;
priority=s[chosen].priority;
}
}
printf("\n Job Num:%d ",(chosen+1));
s[chosen].status=1;
wait_tym=wait_tym+(clock-s[chosen].arrv_tym) ;
clock=clock+s[chosen].svc_tym;
priority=100;
n--;
}
return wait_tym;
void main()
{
int i,j,choice,tot_wait_tym;
for(i=0;i<5;i++)
{
j=i+1;
printf("\nArrv_tym for job %d::",j);
scanf("%d",&s[i].arrv_tym);
printf("\nSvc_tym for job %d::",j);
scanf("%d",&s[i].svc_tym);
s[i].status=0;
printf("\npriority for job num %d :",j);
scanf("%d",&s[i].priority);
}
printf("\nFCFS :: ");
tot_wait_tym=Fcfs();
printf("\nTotal wait tym in Fcfs Is : %d",tot_wait_tym);
printf("\nAvg wait tym in Fcfs is : %d",(tot_wait_tym/5));
printf("\nSJF ::");
tot_wait_tym=Sjf();
printf("\nTotal wait tym in SJF is : %d",tot_wait_tym);
printf("\nAvg wait tym in SJF is : %d",(tot_wait_tym/5));
printf("\nPRIORITY ::");
tot_wait_tym=Priority();
printf("\nTotal wait tym in priority is : %d",tot_wait_tym);
24
printf("\nAvg wait tym in priority is : %d",(tot_wait_tym/5));
output
THEORY:
25
In multiprogramming system using dynamic partitioning there will come a time when all of
the processes in the main memory are in a blocked state and there is insufficient memory. To
avoid wasting processor time waiting for an active process to become unblocked. The OS
will swap one of the processes out of the main memory to make room for a new process or
for a process in Ready Suspend state. Therefore, the OS must choose which process to
replace.
Thus, when a page fault occurs, the OS has to change a page to remove from memory to
make room for the page that must be brought in. If the page to be removed has been modified
while in memory it must be written to disk to bring the disk copy up to date.
Replacement algorithms can affect the system's performance.
First-In-First_Out
Replace the page that has been in memory longest, is the policy applied by FIFO.
Pages from
memory are removed in round-robin fashion. Its advantage is it's simplicity.
This paging algorithm selects a page for replacement that has been unused for the
longest time.
Procedure:
1) Create a queue of pages
2) Select a page to replace based on the following approaches:
i. FIFO
ii. Least Frequently Used
iii. Least Recently Used
Program: FIFO
#include<stdio.h>
int main()
{
int i,j,n,a[50],frame[10],no,k,avail,count=0;
printf("\n ENTER THE NUMBER OF PAGES:\n");
scanf("%d",&n);
printf("\n ENTER THE STRING :\n");
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("\n ENTER THE NUMBER OF FRAMES :");
26
scanf("%d",&no);
for(i=0;i<no;i++)
frame[i]= -1;
j=0;
printf("\tref string\t page frames\n");
for(i=1;i<=n;i++)
{
printf("%d\t\t",a[i]);
avail=0;
for(k=0;k<no;k++)
if(frame[k]==a[i])
avail=1;
if (avail==0)
{
frame[j]=a[i];
j=(j+1)%no;
count++;
for(k=0;k<no;k++)
printf("%d\t",frame[k]);
}
printf("\n");
}
printf("Page Fault Is %d",count);
return 0;
}
output:
27
Program : LRU
#include<stdio.h>
return pos;
}
int main()
{
int no_of_frames, no_of_pages, frames[10], pages[30], counter = 0, time[10], flag1, flag2, i,
j, pos, faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);
28
printf("Enter reference string: ");
if(flag1 == 0){
for(j = 0; j < no_of_frames; ++j){
if(frames[j] == -1){
counter++;
faults++;
frames[j] = pages[i];
time[j] = counter;
flag2 = 1;
break;
}
}
}
if(flag2 == 0){
pos = findLRU(time, no_of_frames);
counter++;
faults++;
frames[pos] = pages[i];
time[pos] = counter;
}
printf("\n");
29
printf("\n\nTotal Page Faults = %d", faults);
return 0;
}
output:
Program LFU:
include<stdio.h>
return pos;
}
int main()
30
{
int no_of_frames, no_of_pages, frames[10], pages[30], counter = 0, time[10], flag1, flag2, i,
j, pos, faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);
if(flag1 == 0){
for(j = 0; j < no_of_frames; ++j){
if(frames[j] == -1){
counter++;
faults++;
frames[j] = pages[i];
time[j] = counter;
flag2 = 1;
break;
}
}
}
if(flag2 == 0){
pos = findLRU(time, no_of_frames);
counter++;
faults++;
frames[pos] = pages[i];
time[pos] = counter;
31
}
printf("\n");
return 0;
}
output:
32
Program:
#include<stdio.h>
#include<unistd.h>
int page[N];
int main()
{
int i;
int logical_address,physical_address,f_no,offset;
for(i=0;i<N;i++)
{
printf("pageno %d: Enter frame no ",i);
scanf(" %d",&page[i]);
}
while(1)
{
printf("Enter the Logical Address :");
scanf("%d",&logical_address);
if(logical_address==-1) break;
f_no=(logical_address/4);
printf("%d %d",f_no,page[f_no]);
offset=logical_address%4;
if(page[f_no]==-1)
printf("\npage fault: given logical address hasn't been loadded in the RAM");
else
{
physical_address=page[f_no]*4+offset;
printf("\nPhysical Address : %d",physical_address);
}
}
33
return 0;
}
Ex.No : 7 Inter Process Communication Shared Memory
Objective:
Description:
IPC stands for Inter-process Communication. This technique allows the processes to
communicate with each another. Since each process has its own address space and unique
user space, how does the process communicate each other?
The answer is Kernel, the heart of the Linux operating system that has access to the whole
memory. So we can request the kernel to allocate the space which can be used to
communicate between processes.
The process can also communicate by having a file accessible to both the processes.
Processes can open, and read/write the file, which requires lot of I/O operation that consumes
time.
ipcs is a UNIX / Linux command, which is used to list the information about the inter-process
communication ipcs command provides a report on System V IPCS (Message queue,
Semaphore, and Shared memory).
34
Server reads from the input file.
The server writes this data in a message using either a pipe, fifo or message queue.
The client reads the data from the IPC channel,again requiring the data to be copied
from kernel’s IPC buffer to the client’s buffer.
Finally the data is copied from the client’s buffer.
A total of four copies of data are required (2 read and 2 write). So, shared memory provides a
way by letting two or more processes share a memory segment. With Shared Memory the
data is only copied twice – from input file into shared memory and from shared memory to
the output file.
shmat(): Before you can use a shared memory segment, you have to attach yourself
to it using shmat(). void *shmat(int shmid ,void *shmaddr ,int shmflg);
shmid is shared memory id. shmaddr specifies specific address to use but we should set
it to zero and OS will automatically choose the address.
shmdt(): When you’re done with the shared memory segment, your program should
detach itself from it using shmdt(). int shmdt(void *shmaddr);
shmctl(): when you detach from shared memory,it is not destroyed. So, to destroy
shmctl() is used. shmctl(int shmid,IPC_RMID,NULL);
Procedure:
Create the server process and create the shared memory portion using shmget()
function.
Attach the shared memory segment to data space and assign the shared memory a key
value say “1234”.
Obtain the shared memory by passing the corresponding key value “1234”.
Read the data put by server in the memory. Alter a character as an acknowledgement
for having read the data.
Program
35
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSZ 27
main()
{
char c;
int shmid,k;
key_t key;
char *shm, *s;
printf("Your key is 5678");
key=5678;
if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0)
{
printf("error in shmget");
exit(1);
}
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{
printf("error in shmat");
exit(1);
}
s = shm;
printf("Enter value");
for(c='a';c<'z';c++)
{
*s=c;
*s++;
36
}
*s=NULL;
while (*shm != '*')
sleep(1);
exit(0);
}
cmem.c[CLIENT PROGRAM]
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSZ 27
main()
{
int shmid,k;
key_t key;
char *shm, *s;
printf("Enter Key to See Data");
if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
perror("shmget");
exit(1);
}
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}
for (s = shm; *s != NULL; s++)
putchar(*s);
37
putchar('\n');
*shm = '*';
exit(0);
}
THEORY:
Deadlock:
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 (including itself).
Waiting for a resource Note that it is usually a non-preempt able (resource). Preempt able
resources can be yanked away and given to another.
Hold and wait: processes request resources incrementally, and hold on to what they've
got.
Circular wait: circular chain of waiting, in which each process is waiting for a resource
held by the next process in the chain.
Deadlock Avoidance
Avoid actions that may lead to a deadlock. Think of it as a state machine moving from one
state to another as each instruction is executed.
Safe State
38
It is not a deadlocked state
To avoid deadlocks, we try to make only those transitions that will take you from one safe
state to another. We avoid transitions to unsafe state (a state that is not deadlocked, and is not
safe).
Algorithm:
8. If the new request comes then check that the system is in safety.
Program:
#include<stdio.h>
char res[10]={'A','B','C','D','E','F','G','H','I','J'};
void disp(int m,int n,int alloc[5][5],int max[5][5],int avble[5],int need[5][5])
;
void safesq(int m,int n,int alloc[5][5],int avble[5],int need[5][5]);
void main()
{
int i,j,ch,n,m,work1[5];
int avble[5],alloc[5][5],max[5][5],need[5][5];
printf("\nENTER THE NUMBER OF PROCESSES : \t");
scanf("%d",&n);
printf("\nENTER THE NUMBER OF RESOURCES : \t");
39
scanf("%d",&m);
printf("\nENTER THE MAXIMUM INSTANCES OF EACH RESOURCE\n");
for(i=0;i<m;i++)
{
printf("\n\tRESOURCE %c:\t",res[i]);
scanf("%d",&avble[i] );
}
printf("\nENTER THE MAXIMUM DEMAND OF EACH PROCESS FOR A RESOURCE\
n");
for(i=0;i<n;i++)
{
printf("\n\tFOR PROCESS P%d \n",i);
for(j=0;j<m;j++)
{
printf("\n\tRESOURCE %c : \t",res[j]);
scanf("%d",&max[i][j]);
}
}
printf("\nENTER THE MAX NO. OF INSTANCES OF A RESOURCE ALLOCATED
TO");
printf(" A PROCESS.\n");
for(i=0;i<n;i++)
{
printf("\n\tFOR PROCESS P%d \n",i);
for(j=0;j<m;j++)
{
printf("\n\tRESOURCE %c : \t",res[j]);
scanf("%d",&alloc[i][j]);
}
}
40
for(i=0;i<m;i++)
{
work1[i]=0;
for(j=0;j<n;j++)
{
work1[i]+=alloc[j][i];
}
printf("%d",work1[i]);
avble[i]=avble[i] - work1[i];
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
need[i][j]=max[i][j]-alloc[i][j];
}
}
while(1)
{
printf("\n\n\tMENU:\n\t1]DISPLAY DATA\n\t2]GENERATE SAFE SEQUENCE");
printf("\n\t3]EXIT\n\tENTER YOUR CHOICE:\t");
scanf("%d",&ch);
switch(ch)
{
case 1:
disp(m,n,alloc,max,avble,need);
break;
case 2:
safesq(m,n,alloc,avble,need);
41
break;
case 3:
exit(0);
default:
printf("\n\tINVALID CHOICE ENTERED.\n");
}
}
}
void disp(int m,int n,int alloc[5][5],int max[5][5],int avble[5],int need[5][5])
{ int i,j;
printf("\n\tALLOCATION\tMAX\tNEED\tAVAIL");
printf("\t\t");
for(i=0;i<4;i++)
{
for(j=0;j<m;j++)
printf("%c ",res[j]);
printf(" ");
}
for(i=0;i<n;i++)
{
printf("\n\tP%d\t",i);
for(j=0;j<m;j++)
printf("%d ",alloc[i][j]);
printf(" ");
for(j=0;j<m;j++)
printf("%d ",max[i][j]);
printf("\t");
for(j=0;j<m;j++)
printf("%d ",need[i][j]);
42
printf(" ");
if(i==0)
{
for(j=0;j<m;j++)
printf("%d ",avble[j]);
}
}
}
void safesq(int m,int n,int alloc[5][5],int avble[5],int need[5][5])
{
int i,j,k=0,l,work[5],work1[5],fin[5],flag=0,flag1=0,safesq[6];
for(i=0;i<m;i++)
work[i]=avble[i];
for(i=0;i<n;i++)
fin[i]=0;
for(l=0;l<n;l++)
{
for(i=0;i<n;i++)
{
flag1=0;
if(fin[i]==0)
{
for(j=0; j<m; j++)
{
if(need[i][j] > work[j])
{
flag1=1;
break;
}
43
}
if(flag1==0)
{
for(j=0;j<m;j++)
work[j]=work[j]+alloc[i][j];
fin[i]=1;
safesq[k]=i;
k++;
}
}
}
}
for(i=0;i<n;i++)
{
if(fin[i]==0)
{
printf("\n\tFOR THE GIVEN REQUIREMENT THE SYSTEM IS");
printf(" NOT IN A SAFE STATE.\n");
flag=1;
break;
}
}
if(flag==0)
{
printf("\n\tTHE SAFE SEQUENCE IS:\t");
for(i=0;i<n;i++)
printf("P%d ",safesq[i]);
}
}
44
Ex.No : 09 Concurrency and Synchronization.
Procedure:
Program:
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
int array[5];
sem_t mutex;
sem_t empty;
sem_t full;
int p_tid;
int c_tid;
int produce_item();
void insert_item(int);
45
int remove();
void * produce()
int item;
while(1)
item=produce_item();
sem_wait(&empty);
sem_wait(&mutex);
insert_item(item);
sem_post(&mutex);
sem_post(&full);
void *consumer()
int item;
while(1)
sleep(20);
sem_wait(&full);
sem_wait(&mutex);
item=remove_item();
46
sem_post(&mutex);
sem_post(&empty);
int produce_item()
return a++;
rear = rear+1;
rear = rear % 5;
array[rear] = item;
int remove_item()
front = front+1;
front = front%5;
return item;
int main()
int i;
47
pthread_attr_t *attr = NULL;
pthread_t p_tid;
pthread_t c_tid;
sem_init(&mutex,0,1);
sem_init(&empty,0,5);
sem_init(&full,0,0);
pthread_create(&p_tid,attr,produce,0);
pthread_create(&c_tid,attr,consumer,0);
pthread_join(p_tid,NULL);
pthread_join(c_tid,NULL);
return 0;
Objective:
Procedure
Program
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
void* reader(void*);
void* writer(void*);
int wc = 0;
int write_request = 0;
int main()
pthread_t readers[MAXTHREAD],writerTh;
int index;
*/
sem_init (&q,0,1);
ids[index]=index+1;
if(pthread_create(&readers[index],0,reader,&ids[index])!=0){
exit(1);
if(pthread_create(&writerTh,0,writer,0)!=0){
exit(1);
pthread_join(writerTh,0);
49
sem_destroy (&q);
return 0;
int can_read;
while(1){
can_read = 1;
sem_wait(&q);
else can_read = 0;
sem_post(&q);
if(can_read) {
access_database();
sleep(index);
sem_wait(&q);
rc--;
sem_post(&q);
sched_yield();
return 0;
50
{
int can_write;
while(1){
can_write = 1;
non_access_database();
sem_wait (&q);
if(rc == 0) wc++;
sem_post(&q);
if(can_write) {
access_database();
sleep(3);
sem_wait(&q);
wc--;
write_request = 0;
sem_post(&q);
sched_yield();
return 0;
void access_database()
void non_access_database()
51
}
a) Contiguous
b) Linked
Objective:
Procedure:
Sequential Allocation:
Create an array of structure and implement best fit and first fit
Linked Allocation:
#include <stdio.h>
#include <string.h>
struct student
int m[3];
float avg;
char name[25];
} a[5],b[5];
int main()
int i,j;
FILE *fp;
fp=fopen("records.txt","w");
for (i=0;i<3;i++)
52
{
int sum=0;
scanf("%s",&a[i].name);
for (j=0;j<3;j++)
scanf("%d",&a[i].m[j]);
sum+=a[i].m[j];
a[i].avg=sum/3;
strcpy(b[i].name,a[i].name);
b[i].avg=a[i].avg;
fwrite(&b[i],sizeof(struct student),1,fp);
fclose(fp);
fp=fopen("records.txt","r");
for(i=0;i<3;i++)
fread(&b[i],sizeof(struct student),1,fp);
printf("\n Average:%f",a[i].avg);
return(0);
//// Linked
#include<stdlib.h>
53
#include<stdio.h>
#include<string.h>
struct student
char name[10];
int marks[3];
float avg;
}st;
int main()
int i,n,j;
FILE *fp;
scanf("%d",&n);
bs=s;
fp=fopen("output.txt","w");
for (i=0;i<n;i++)
float sum=0;
scanf("%s",s->name);
for (j=0;j<3;j++)
54
scanf("%d",&s->marks[j]);
sum+=s->marks[j];
s->avg = sum/3.0;
strcpy(st.name,s->name);
st.avg=s->avg;
write(&st,sizeof(struct student),1,fp);
s->next=ne;
s=ne;
fclose(fp);
fp=fopen("output.txt","r");
s=bs;
for(i=0;i<n;i++)
fread(&st,sizeof(struct student),1,fp);
printf("\n Average:%f",s->avg);
s=s->next;
return(0);
Objective:
55
Procedure:
Input memory capacity, partition size, no. of processes and for each process required amount
of memory
Input memory capacity, no.of partitions, sizes of each partition, no. of processes and for each
process required amount of memory
#include<stdio.h>
#include<conio.h>
main()
{
intms, bs, nob, ef,n, mp[10],tif=0;
inti,p=0;
clrscr();
printf("Enter the total memory available (in Bytes) -- ");
scanf("%d",&ms);
printf("Enter the block size (in Bytes) -- ");
scanf("%d", &bs);
nob=ms/bs;
ef=ms - nob*bs;
printf("\nEnter the number of processes -- ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter memory required for process %d (in Bytes)-- ",i+1);
scanf("%d",&mp[i]);
}
printf("\nNo. of Blocks available in memory -- %d",nob);
printf("\n\nPROCESS\tMEMORY REQUIRED\t ALLOCATED\tINTERNAL
FRAGMENTATION");
for(i=0;i<n && p<nob;i++)
{
printf("\n %d\t\t%d",i+1,mp[i]);
if(mp[i] >bs)
printf("\t\tNO\t\t---");
else
{
printf("\t\tYES\t%d",bs-mp[i]);
tif = tif + bs-mp[i];
p++;
}
}
56
if(i<n)
printf("\nMemory is Full, Remaining Processes cannot be accomodated");
printf("\n\nTotal Internal Fragmentation is %d",tif);
printf("\nTotal External Fragmentation is %d",ef);
getch();
}
#include<stdio.h>
#include<conio.h>
main()
{
intms,mp[10],i, temp,n=0;
charch = 'y';
clrscr();
printf("\nEnter the total memory available (in Bytes)-- ");
scanf("%d",&ms);
temp=ms;
for(i=0;ch=='y';i++,n++)
{
printf("\nEnter memory required for process %d (in Bytes) -- ",i+1);
scanf("%d",&mp[i]);
if(mp[i]<=temp)
{
printf("\nMemory is allocated for Process %d ",i+1);
temp = temp - mp[i];
}
else
{
printf("\nMemory is Full");
break;
}
printf("\nDo you want to continue(y/n) -- ");
scanf(" %c", &ch);
}
printf("\n\nTotal Memory Available -- %d", ms);
printf("\n\n\tPROCESS\t\t MEMORY ALLOCATED ");
for(i=0;i<n;i++)
printf("\n \t%d\t\t%d",i+1,mp[i]);
printf("\n\nTotal Memory Allocated is %d",ms-temp);
printf("\nTotal External Fragmentation is %d",temp);
getch();
}
Ex.No 12 Adding new system call to Linux Kernel
Objective:
Adding our own developed system call to Linux kernel.
Procedure:
57
1) Download the latest version of the 2.6 Linux kernel from
www.kernel.org.
2) Unzip and untar the kernel directory into /usr/src/.
3) In /usr/src/Linux-x.x.x/kernel/, Create a new file myservice.c to define your system call.
4) In /usr/src/Linux-x.x.x/include/asm/unistd.h, define an index for your system call. Your
index should be the number after the last system call defined in the list.
5) Also, you should increment the system call count.
6) In /usr/src/Linux-x.x.x/arch/i386/kernel/entry.S, you should define a pointer to hold a
reference to your system call routine.
7) Add your system call to the Makefile in /usr/src/Linuxx.x.x/kernel/Makefile
8) Make your system from /usr/src/Linux-x.x.x
9) Add a new boot image to Lilo, by editing /etc/lilo.conf. Your lilo configuration will vary
slightly.
10) Making a user test file. You also need to copy your edited unistd.h from /usr/src/Linux-
x.x.x/include/asm/ to /usr/include/kernel/ because it contains your system call’s index.
11) Reboot into your new kernel and compile your user test program to try out your system
call. You will know if it worked if you see a kernel message in /var/log/kernel/warnings
announcing that your service is running.
58