SS Manual GEC 18CSL66
SS Manual GEC 18CSL66
SS Manual GEC 18CSL66
VTU SYLLABUS
Subject Code: 18CSL66 I.A. Marks : 40
Description (If any): Exercises to be prepared with minimum three files (Where ever necessary):
i. Header file.
The idea behind using three files is to differentiate between the developer and user sides. In the
developer side, all the three files could be made visible. For the user side only header file and
application files could be made visible, which means that the object code of the implementation file
could be given to the user along with the interface given in the header file, hiding the source file, if
required. Avoid I/O operations (printf/scanf) and use data input file where ever it is possible
Laboratory Experiments:
1) a) Write a LEX program to recognize valid arithmetic expression. Identifiers in the expression
could be only integers and operators could be + and *. Count the identifiers & operators present
and print them separately.
2) Develop, Implement and execute a program using YACC tool to recognize all strings ending with
b preceded by n a’s using the grammar anb (note: input n value).
3) Design, develop and implement YACC/C program to construct Predictive / LL(1) Parsing Table
for the grammar rules: A →aBa , B →bB | ε. Use this table to parse the sentence: abba$.
4) Design, develop and implement YACC/C program to demonstrate Shift Reduce Parsing technique
for the grammar rules: E →E+T | T, T →T*F | F, F →(E) | id and parse the sentence: id + id * id.
5) Design, develop and implement a C/Java program to generate the machine code using Triples for
the statement A = -B * (C +D) whose intermediate code in three-address form:
T1 = -B
T2 = C + D
1
T3 = T1 +
T2 A = T3
6. a) Write a LEX program to eliminate comment lines in a C program and copy the resulting
program into a separate file.
b) Write YACC program to recognize valid identifier, operators and keywords in the given text
(C program) file.
2
1. Introduction to LEX
Lex and YACC helps you write programs that transforms structured input. Lex generates C
code for lexical analyzer whereas YACC generates Code for Syntax analyzer. Lexical analyzer is
build using a tool called LEX. Input is given to LEX and lexical analyzer is generated.
Lex is a UNIX utility. It is a program generator designed for lexical processing of character
input streams. Lex generates C code for lexical analyzer. It uses the patterns that match strings
inthe input and converts the strings to tokens. Lex helps you by taking a set of descriptions
ofpossible tokens and producing a C routine, which we call a lexical analyzer. The token
descriptions that Lex uses are known as regular expressions.
nd
2 Step: lex prg1.l
rd
3 Step: cc lex.yy.c –ll
th
4 Step: ./a.out
DEFINITION
SECTION
%%
RULE SECTION
%%
CODE SECTION
3
% is a delimiter to the mark the beginning of the Rule section. The second %% is optional, but
the first is required to mark the beginning of the rules. The definitions and the code /subroutines
are often omitted.
Lex variables
yyin Of the type FILE*. This points to the current file being parsed by the lexer.
yyout Of the type FILE*. This points to the location where the output of the lexer will be
written. By default, both yyin and yyout point to standard input and output.
yytext The text of the matched pattern is stored in this variable (char*).
yylineno Provides current line number information. (May or may not be supported by the
lexer.
Lex functions
yylex() The function that starts the analysis. It is automatically generated by Lex.
yywrap() This function is called when end of file (or input) is encountered. If this function
returns 1, the parsing stops. So, this can be used to parse multiple files. Code can
be written in the third section, which will allow multiple files to be parsed. The
strategy is to make yyin file pointer (see the preceding table) point to a different
file until all the files are parsed. At the end, yywrap() can return 1 to indicate end
of parsing.
yyless(int n) This function can be used to push back all but first ‘n’ characters of the read token.
yymore() This function tells the lexer to append the next token to the current token.
4
special meaning in Lex. The following two tables define some of the symbols used in Lex and
give a few typical examples.
Character Meaning
A-Z, 0-9, a-z Characters and numbers that form part of the pattern.
2. Introduction to YACC
YACC provides a general tool for imposing structure on the input to a computer program. The
input specification is a collection of grammar rules. Each rule describes an allowable structure
and gives it a name. YACC prepares a specification of the input process. YACC generates a
function to control the input process. This function is called a parser.
The name is an acronym for “Yet Another Compiler Compiler”. YACC generates the code for
the parser in the C programming language. YACC was developed at AT& T for the Unix
operating system. YACC has also been rewritten for other languages, including Java, Ada.
The function parser calls the lexical analyzer to pick up the tokens from the input stream.
These tokens are organized according to the input structure rules .The input structure rule is called
as grammar. When one of the rule is recognized, then user code supplied for this rule ( user code
is action) is invoked. Actions have the ability to return values and makes use of the values of
other actions.
5
2.1 Steps in writing YACC Program:
st
1 step: Using gedit editor create a file with extension y. For example: prg1.y
nd
2 Step: YACC –d prg1.y
rd
3 Step: lex prg1.l
th
4 Step: cc y.tab.c lex.yy.c -ll
When we run YACC, it generates a parser in file y.tab.c and also creates an include file y.tab.h.
To obtain tokens, YACC calls yylex. Function yylex has a return type of int, and returns the token.
Values associated with the token are returned by lex in variable yylval.
The general format for the YACC file is very similar to that of the Lex file.
DEFINITION SECTION
%%
RULE SECTION
%%
CODE SECTION
6
Definition Section
%union It defines the Stack type for the Parser. It is a union of various datas/structures/
objects
%token These are the terminals returned by the yylex function to the YACC. A token can
also have type associated with it for good type checking and syntax directed
translation. A type of a token can be specified as %token <stack
member>tokenName.
Ex: %token NAME NUMBER
%type The type of a non-terminal symbol in the Grammar rule can be specified with
this.The format is %type <stack member>non-terminal.
%start Specifies the L.H.S non-terminal symbol of a production rule which should be
taken as the starting point of the grammar rules.
%prec Changes the precedence level associated with a particular rule to that of the
following token name or literal
Rules Section
The rules section simply consists of a list of grammar rules. A grammar rule has the form:
A: BODY
7
A represents a nonterminal name, the colon and the semicolon are YACC punctuation and
BODY represents names and literals. The names used in the body of a grammar rule may represent
tokens or nonterminal symbols. The literal consists of a character enclosed in single quotes.
With each grammar rule, the user may associate actions to be. These actions may return values,
and may obtain the values returned by the previous actions. Lexical analyzer can return values for
tokens, if desired. An action is an arbitrary C statement. Actions are enclosed in curly braces.
8
Apart from the program code, it includes the current activity represented by
Program Counter,
Contents of Processor registers,
Process Stack which contains temporary data like function parameters, return addresses and local
variables
Data section which contains global variables
Heap for dynamic memory allocation
A Multi-programmed system can have many processes running simultaneously with the CPU
multiplexed among them. By switching the CPU between the processes, the OS can make the computer
more productive. There is Process Scheduler which selects the process among many processes that are
ready, for program execution on the CPU. Switching the CPU to another process requires performing a
state save of the current process and a state restore of new process, this is Context Switch.
CPU utilization:
Throughput: The number of processes that are completed per unit time.
Waiting time: The sum of periods spent waiting in ready queue.
Turnaround time: The interval between the time of submission of process to the time of
completion.
Response time: The time from submission of a request until the first response is produced.
The different scheduling algorithms are
FCFS: First Come First Served Scheduling
4.2 Deadlocks
A process requests resources; and if the resource is not available at that time, the process enters a waiting
state. Sometimes, a waiting process is never able to change state, because the resource is has requested is
held by another process which is also waiting. This situation is called Deadlock. Deadlock is
characterized by four necessary conditions.
Mutual Exclusion
9
Hold and Wait
No Preemption
Circular Wait
10
LEX and YACC Programs:
1.a) Write a LEX program to recognize valid arithmetic expression. Identifiers in the
expression could be only integers and operators could be + and *. Count the identifiers & operators
present and print them separately.
b) Write YACC program to evaluate arithmetic expression involving operators: +, -,
*, and /
Program 1a:
1a.l(Lex Part)
%{
int v=0, opr=0,id=0,flag=0;
%}
%%
[0-9a-zA-Z]+[0-9A-Za-z]* {id++; printf(“\n identifier\t%s”,yytext);}
[\+\-\*\/\%] {opr++ ; printf("%s is a operator ",yytext);}
“(“ {v++;}
“)” {v--;}
“;” {flag=1;}
.|\n { ;}
%%
int main()
{
printf("enter arithmtic expression:\n");
yylex();
if((opr+1)==id&&v==0&&flag==0)
{
printf(“\nidentifier count=%d”,id);
printf(“\noperator count=%d”,opr);
printf("valid expression\n");12
else
printf("invalid expression\n");
}
Output
$lex 1a.l
$cc lex.yy.c
$./a.out
Enter arithmtic expression : 5 + ab – 69 * 50 ( enter Ctrl-D)
5 is a operand
+ is a operator
ab is a operand
– is a operator
69 is a operand
* is a operator
11
50 is a operand
valid expression
12
Program 1b:
1b.l(Lex Part)
%{
#include "y.tab.h"
Extern int yylval=0;
%}
NUM [0-9]
%%
{NUM}+ {yylval=atoi(yytext); return(A);}
. { return(yytext[0]); }
\n { return 0; }
%%
yywrap()
{
}
%token A
%start st
%%
#include “y.tab.c”
#include<stdio.h>
int main()
{
printf("\n enter the expression\n");
yyparse();
Output
$lex 1b.l
$yacc-d 1b.y
$cc 1b.c
$./a.out
14
2. Develop, Implement and Execute a program using YACC tool to recognize all stringsending with
b preceded by n a’s using the grammar an b (note: input n value)
Program 2a:
2a.l(Lex Part)
%{
#include "y.tab.h"
int n=0,m=0;
%}
%%
[a|A]* {n=strlen(yytext); return(A);}
[b|B]+ {m=strlen(yytext); return(B);}
. {return(yytext[0]);}
\n {return 0;}
%%
2a.y(YACC Part)
%{
#include “lex.yy.c”
int valid=0;
%}
%token A B
%start st
%%
st: A B{ if((n>0) &&(m==1)) valid=1;}
;
%%
yyerror()
{
}
#include”y.tab.c”
#include<stdio.h>
main()
{
printf(“enter the expression\n”);
yyparse();
if(valid==1)
printf(“valid expression\n”);
else
printf(“invalid expression\n”);
}
15
Output
$lex 2b.l
$yacc-d 2b.y
$cc lex.yy.cy.tab.c -ll
$./a.out
3. Design, develop and implement YACC/C program to construct Predictive / LL(1) Parsing Table
for the grammar rules: A →aBa , B →bB | ε. Use this table to parse the sentence: abba$.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
charip[20],stack[20];
int main()
{
char m[2][3][10]={ {"aBa","E","E"},
{"n","bB","n"} };
int size[2][3]= {3,1,1,1,2,1};
inti,j,k,n,row,col;
16
printf("\n Enter the input string: ");
scanf("%s",ip);
strcat(ip,"$");
n=strlen(ip);
stack[0]='$';
stack[1]='A';
i=1;
j=0;
printf("\nStack\t\tInput\n");
printf("________\t\t_________\n");
while((stack[i]!='$')&&(ip[j]!='$')) /* to check stack and input both contains $ */
{
if(stack[i]==ip[j]) /* input and stack matches, discard stack and move to next input symbol */
{
i--;
j++;
}
switch(stack[i])
{
case 'A': row=0;
break;
case 'B': row=1;
break;
}
switch(ip[j])
{
case 'a': col=0;
if(stack[i]=='$')
{
printf("error");
exit(0);
}
break;
case 'b': col=1;
if(stack[i]=='$')
{
17
printf("error");
exit(0);
}
break;
case '$': col=2;
if(stack[i]!='$')
{
printf("error");
exit(0);
}
break;
}
if(m[row][col][0]=='E') /* to check error entry*/
{
printf("\nERROR");
exit(0);
}
else if(m[row][col][0]=='n') /* to check for epsilon*/
i--;
else if(m[row][col][0]==ip[j]) /*to check top of stack and input are equal*/
{
for(k=size[row][col]-1;k>=0;k--) /* to replace non terminal by its production*/
{
stack[i]=m[row][col][k];
i++;
}
i--; /* points to top of stack*/
}
for(k=0;k<=i;k++)
printf("%c",stack[k]); /* update stack*/
printf("\t\t");
for(k=j;k<=n;k++)
printf("%c",ip[k]); /* update input*/
printf("\n");
}
k--;
18
if (i<0)
printf("\n SUCCESS");
else
printf("\n Error");
return 0;
}
Output:
19
4. Design, develop and implement YACC/C program to demonstrate Shift Reduce Parsing technique
for the grammar rules: E →E+T | T, T →T*F | F, F → (E) | id and parse the sentence: id + id * id.
A parser is a compiler or interpreter component that breaks data into smaller elements for easy
translation into another language. A parser takes input in the form of a sequence of tokens or
program instructions and usually builds a data structure in the form of a parse tree or an abstract
syntax tree.
A parser's main purpose is to determine if input data may be derived from the start symbol of the
grammar.
Syntax analyzers follow production rules defined by means of context-free grammar. The way the
production rules are implemented (derivation) divides parsing into two types: top-down parsing and
bottom-up parsing.
Top-down Parsing
When the parser starts constructing the parse tree from the start symbol and then tries to transform
the start symbol to the input, it is called top-down parsing.
Backtracking: It means, if one derivation of a production fails, the syntax analyzer restarts the
processusing different rules of same production. This technique may process the input string more
than once to determine the right production.
20
Bottom-up Parsing
Bottom-up parsing starts with the input symbols and tries to construct the parse tree up to the start
symbol.
Shift-reduce Parsing (Bottom-up Parsing)
Shift-reduce parsing attempts to construct a parse tree for an input string beginning at the leaves and
working up towards the root. In other words, it is a process of “reducing” (opposite of deriving a
symbol using a production rule) a string w to the start symbol of a grammar. At every (reduction) step,
a particular substring matching the RHS of a production rule is replaced by the symbol on the LHS of
the production.
A general form of shift-reduce parsing is LR (scanning from Left to right and using Right-most
derivation in reverse) parsing, which is used in a number of automatic parser generators like Yacc,
Bison, etc.
include<stdio.h>
#include<conio.h>
#include<string.h>
int k=0,z=0,i=0,j=0,c=0;
char a[16],ac[20],stk[15],act[10];
void check();
void main()
gets(a);
c=strlen(a);
strcpy(act,"SHIFT->");
21
puts("Stack \t Input \t Action");
for(k=0,i=0;j<c;k++,i++,j++)
stk[i]=a[j];
stk[i+1]=a[j+1];
stk[i+2]='\0';
a[j]=' ';
a[j+1]=' ';
printf("\n$%s\t%s$\t%sid",stk,a,act);
check();
else
stk[i]=a[j];
stk[i+1]='\0';
a[j]=' ';
printf("\n$%s\t%s$\t%ssymbol",stk,a,act);
check();
getch();
22
void check()
strcpy(ac,"REDUCE");
for(z=0;z<c;z++)
if(stk[z]=='(' &&stk[z+1]=='E'&&stk[z+2]==')')
stk[z]='F';
stk[z+1]='\0';
stk[z+2]='\0';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
i=i-2;
for(z=0;z<c;z++)
if(stk[z]=='i' &&stk[z+1]=='d')
stk[z]='F';
stk[z+1]='\0';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
j++;
for(z=0;z<c;z++)
23
{
stk[z]='T';
stk[z+1]='\0';
stk[z+2]='\0';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
i=i-2;
else if(stk[z]=='F')
stk[z]='T';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
for(z=0;z<c;z++)
break;
if(a[j+1]=='*')
break;
else
24
{
stk[z]='E';
stk[z+1]='\0';
stk[z+2]='\0';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
i=i-2;
else if(stk[z]=='T')
stk[z]='E';
printf("\n$%s\t%s$\t%sid",stk,a,ac);
Output:
25
5. Design, develop and implement a C/Java program to generate the machine code using Triples for the
statement A = -B * (C +D) whose intermediate code in three-address form:
T1 = -B
T2 = C + D
T3 = T1 *
T2 A = T3
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
char op[2],arg1[5],arg2[5],result[5];
void main()
{
while(!feof(fp1))
{
fscanf(fp1,"%s%s%s%s",result,arg1,op,arg2);
if(strcmp(op,"+")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nADD R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"*")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMUL R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"-")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nSUB R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"/")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nDIV R0,%s",arg2);
26
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"=")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMOV %s,R0",result);
}
}
fclose(fp1);
fclose(fp2);
getch();
}
Output:
input.txt output.txt
T1 -B = ? MOV R0,-B
T2 C + D MOV T1,R0
T3 T1 * T2 MOV R0,C
A T3 = ? ADD R0,D
MOV T2,R0
MOV R0,T1
MUL R0,T2
MOV T3,R0
MOV R0,T3
MOV A,R0
27
6.a) Write a LEX program to eliminate comment lines in a C program and copy the
resulting program into a separate file.
b) Write YACC program to recognize valid identifier, operators and keywords in the
given text (C program) file.
Program 6a:
%{
#include<stdio.h>
int c_count=0;
%}
%%
“/*”[^*/]*/” {c_count ++;}
“//”.* {c_count++;}
%%
int main(int argc,char **argv)
{
FILE *f1,*f2;
If(argc>1)
{
f1=fopen(argv[1],”r”);
if(!f1)
{ printf(“file error\n”);
exit(1);
}
yyin=f1;
f2=fopen(argv[2],”w”);
if(!f2)
{
printf(“error”);
exit(1);
}
yyout=f2;
yylex();
printf(“number of comment lines:%d\n”,c_count);
}
return 0;
}
}
28
Outout:
}
}
lex f.l
cc lec.yy.c –ll
./a.out inputfile outputfile
gedit inputfile
int main()
{
//variable declaration
int a,b,c;
/*addition*/
c=a+b;
return 0
}
gedit outputfile
int main()
{
int a,b,c;
c=a+b;
return 0
}
number of comment lines:2
29
6b.Write YACC program to recognize valid identifier, operators and keywords in the given text (C
program) file.
%{ #include <stdio.h>
#include "y.tab.h“
extern yylval;
%}
%%
[ \t] ;
[+|-|*|/|=|] {printf("operator is %s\n",yytext); return OP;}
[0-9]+ {yylval = atoi(yytext); printf("numbers is %d\n",yylval); return DIGIT;}
int|char|bool|float|void|for|do|while|if|else|return|void {printf("keyword is %s\n",yytext);
return KEY;}
[a-zA-Z0-9]+ {printf("identifier is %s\n",yytext); return ID;}
. ;
%%
Yacc File(f.y)
%{ #include <stdio.h>
#include<stdlib.h>
int id=0, dig=0, key=0, op=0;
%}
%token DIGIT ID KEY OP
%%
input: DIGIT input { dig++; }
| ID input { id++; }
| KEY input { key++; }
| OP input {op++;}
| DIGIT { dig++; }
| ID { id++; }
| KEY { key++; }
| OP { op++;} ;
%%
C file(f.c)
#include<stdio.h>
extern int yylex();
extern int yyparse();
extern FILE *yyin;
main()
{
FILE *myfile = fopen("sam_input.c", "r");
if (!myfile)
{ printf("I can't open sam_input.c!");
return -1;
}
yyin = myfile;
do
{
yyparse();
} while (!feof(yyin));
30
printf("numbers = %d\nKeywords = %d\nIdentifiers = %d\noperators = %d\n", dig, key,id, op);
}
void yyerror()
{
printf("EEK, parse error! Message: ");
exit(-1);
}
31
7. Design, develop and execute a program in C / C++ to simulate the working of Shortest
Remaining Time and Round-Robin Scheduling Algorithms. Experiment with different
quantum sizes for the Round-Robin algorithm. In all cases, determine the average turn -
around time. The input can be read from key board or from a file.
The name of the algorithm comes from the round-robin principle known from other fields,
where each person takes an equal share of something in turn.
#include<stdio.h>
void sjf()
{
inti,j,bt[10],n,pt[10],wt[10],tt[10],t,k;
floatat,aw, w1=0.0,t1=0.0;
printf(“\n enter no of jobs”);
scanf(“%d”,&n);
printf(“\n enter burst time”);
for(i=0;i<n;i++)
scanf”(%d”,&bt[i]);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(bt[i]<bt[j])
{
t=bt[i];
bt[i]=bt[j];
bt[j]=t;
}
wt[0]=0;
for(i=0;i<n;i++)
{
wt[i+1]=bt[i]+wt[i];
tt[i]=wt[i]+bt[i];
w1=w1+wt[i];
t1=t1+tt[i];
}
aw=w1/n;
at=t1/n;
printf(“\n bt\t wt\t tt”);
32
for(i=0;i<n;i++)
printf(“%d\t%d\t%d\n”,bt[i],wt[i],tt[i]);
printf(“aw=%f\n at=%f”,aw,at);
}
/*
*/
void roundrobin()
{
int s[10],st[10],p[10],n,i,j,w[10],t[10],tq,tst=0,w1=0;
floattt=0.0,tw=0.0,aw,at;
printf("\n enter the no of process");
scanf("%d",&n);
printf("\n enter the time quantum");
scanf("%d",&tq);
printf("\n enter the process and burst time");
for(i=0;i<n;i++)
scanf("%d %d",&p[i],&s[i]);
for(i=0;i<n;i++)
{
st[i]=s[i];
tst=tst+s[i];
}
for(j=0;j<tst;j++)
for(i=0;i<n;i++)
if(s[i]>tq)
{
s[i]=s[i]-tq;
w1=w1+tq;
t[i]=w1;
w[i]=t[i]-st[i];
}
else if(s[i]!=0)
{
w1=w1+tq;
t[i]=w1;
w[i]=t[i]-st[i];
s[i]=s[i]-tq;
}
for(i=0;i<n;i++)
{
tw=tw+w[i];
tt=tt+t[i];
}
aw=tw/n;
at=tt/n;
printf("process tsttwttt\n");
for(i=0;i<n;i++)
printf("%d %d %d %d\n",p[i],st[i],w[i],t[i]);
printf("aw=%f at=%f\n",aw,at);
}
33
main()
{
int choice;
clrscr();
printf(“enter the choice”);
scanf(“%d”,&choice);
switch(choice)
{
case 1:sjf();
break;
case 2:roundrobin();
Break;
Case 3:exit(0);
return 0;
}
}
/*
Input
Enter the choice : 1
Input
Enter no of jobs
4
Enter burst time
5
12
8
20
Output:
Bt wt tt
5 0 5
8 5 13
12 13 25
20 25 45
aw=10.75000
at=22.000000
Choice 2
Enter no of process: 3
34
2 6
3 2
Output
Process bt wt tat
1 4 4 8
2 6 6 12
3 2 4 6
Awt = 4.666667
atat = 8.666667
35
8. Design, develop and run a program to implement the Banker’s Algorithm. Demonstrate
its working with different data values.
The algorithm was developed in the design process for the operating system and
originally described (in Dutch) in EWD108. When a new process enters a system, it
must declare the maximum number of instances of each resource type that it may ever
claim; clearly, that number may not exceed the total number of resources in the system.
Also, when a process gets all its requested resources it must return them in a finite
amount of time.
#include<stdio.h>
#include<conio.h>
void main()
{
intalloc[7][5],max[7][5],need[7][5],avail[5],finish[7];
intrsrc[5],safe[5];
intp,r,count=0,i,j,total,loopc=1,k=0;
clrscr();
for(i=1;i<=7;i++)
finish[i]=0;
36
for(i=1;i<=p;i++)
{
printf("\nFor process %d: ",i);
for(j=1;j<=r;j++)
scanf("%d",&max[i][j]);
}
for(j=1;j<=r;j++)
{
total=0;
avail[j]=0;
for(i=1;i<=p;i++)
total+=alloc[i][j];
avail[j]=rsrc[j]-total;
}
for(i=1;i<=p;i++)
{
for(j=1;j<=r;j++)
need[i][j]=max[i][j]-alloc[i][j];
}
printf("\t\t");
for(j=1;j<=r;j++)
printf("%d ",max[i][j]);
printf("\t\t");
for(j=1;j<=r;j++)
printf("%d ",need[i][j]);
printf("\n");
}
while(loopc<p&&count!=p)
{
++loopc;
37
for(i=1;i<=p;i++)
{
if(finish[i]==0)
{ for(j=1;j<=r;j++)
{
if(need[i][j]>avail[j])
break;
}
if(j==r+1)
{
for(j=1;j<=r;j++)
avail[j]+=alloc[i][j];
finish[i]=1;
++count;
safe[k++]=i;
}
}
}
}
if(count==p)
{
printf("\nThe system is in a safe state!!\nSafe sequence: ");
for(k=0;k<p;k++)
printf("->%d",safe[k]);
}
else
printf("\nThe system is in an unsafe state!!");
getch();
}
Output
38
2010 3211 1201
1100 1202 0102
1100 1120 0020
1010 3210 2200
0101 2101 2000
39
9. Design, develop and implement a C/C++/Java program to implement page replacement
algorithms LRU and FIFO. Assume suitable input required to demonstrate the results.
When the page that was selected for replacement and paged out is referenced
again it has to be paged in (read in from disk), and this involves waiting for I/O
completion. This determines the quality of the page replacement algorithm: the less time
waiting for page-ins, the better the algorithm. A page replacement algorithm looks at the
limited information about accesses to the pages provided by hardware, and tries to guess
which pages should be replaced to minimize the total number of page misses, while
balancing this with the costs (primary storage and processor time) of the algorithm
itself.
The page replacing problem is a typical online problem from the competitive
analysis perspective in the sense that the optimal deterministic algorithm is known.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void FIFO(char[],char[],int,int);
voidlru(char[],char[],int,int);
intfindLRU(int[],int);
int main()
{
intch,YN=1,i,l,f;
char F[10],s[25];
printf("\nEnter the no of empty Frames: ");
scanf("%d",&f);
for(i=0;i<f;i++) F[i]=-1; //initializing frames
do
{
printf("Enter the string: ");
scanf("%s",s);
l=strlen(s);
printf("\n\n****MENU*****\n\n");
40
printf("\n1.FIFO\n\n2.LRU\n\n3.EXIT");
printf("\nEnter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
for(i=0;i<f;i++)
{
F[i]=-1;
}
FIFO(s,F,l,f);
break;
case 2:
for(i=0;i<f;i++)
{
F[i]=-1;
}
lru(s,F,l,f);
break;
case 3:
exit(0);
}
printf("\n\nTo continue if yess press 1 else press 0\n");
scanf("%d",&YN);
}while(YN==1);
return(0);
}
for(k=0;k<f;k++)
{
if(F[k]==s[i])
flag=1;
}
if(flag==0)
{
printf("\n\t %c\t",s[i]);
F[j]=s[i];
j++;
for(k=0;k<f;k++)
{
printf("%c",F[k]);
}
printf("\tPage-Fault %d",cnt);
cnt++;
}
else
{
flag=0;
printf("\n\t %c\t",s[i]);
for(k=0;k<f;k++)
41
{
printf("%c",F[k]);
}
printf("\tNo page fault");
}
if(j==f)
j=0;
}
}
printf("\n\nPAGE\tFRAMES\tFAULTS");
42
F[pos] = s[i];
lru[pos] = counter;
}
//printing frames
for(int k=0;k<f;k++)
printf("%c",F[k]);
if(flag1==0 || flag2==0)
printf("\t Page-fault %d",faults);
else
printf("\t No page fault");
}
}
return pos;
}
OUTPUT:
Enter the no of empty frames: 3
Enter the length of the string: 5
Enter the string: hello
*********** MENU ***********
1:FIFO
2:LRU
4:EXIT
43
e H e Page-fault 1
l H e l Page-fault 2
l H e l No page-fault
o O e l Page-fault 3
44
Sample Viva Questions
45
+ matches one or more occurrence of the preceding regular expression
eg.: [0-9]+ matches 1 or 1111 or 12345 but not empty string.
? matches zero or occurrence of preceding regular expression.
Eg.: ?[0-9]+ matches a signed number with or without minus sign.
| is like ‘OR’
21.What is an Assembler?
Assembler for an assembly language, a computer program to translate between lower-
level representations of computer programs.
46
23 .Explain yyleng?
Yyleng-contains the length of the string our lexer recognizes.
47
Ans: If several jobs are ready to be brought in to memory, and if there is not enough room
for all of them, then the system must choose among them. Making this decision is job
scheduling.
9. What is a Dispatcher?
Ans: The dispatcher is the module that gives control of the CPU to the process selected by
the short-term scheduler. This function involves: • Switching context • Switching to
user mode • Jumping to the proper location in the user program to restart that program.
12. How can a user program disrupt the normal operations of a system?
Ans: user program may disrupt the normal operation of a system by
Issuing illegal I/O operations
by accessing memory locations within the OS itself
Refusing to relinquish the CPU
48
register and the limit register. The base register holds the smallest legal physical
address; the limit register contains the size of the range. The base and limit registers can be
loaded only by the OS using special privileged instructions.
49