0% found this document useful (0 votes)
43 views132 pages

Aids Os Lab

Uploaded by

v15774239
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views132 pages

Aids Os Lab

Uploaded by

v15774239
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 132

An Autonomous Institution

Approved by AICTE, Affiliated to Anna University, Chennai.


ISO 9001:2015 Certified Institution, Accredited by NBA (BME, CSE, ECE, EEE, IT & MECH),
Accredited by NAAC.
#42, Avadi-Vel Tech Road, Avadi, Chennai- 600062, Tamil Nadu, India.
DEPARTMENT OF ARTIFICIAL INTELLIGENCE AND DATA SCIENCE

191CS42B/ OPERATING SYSTEMS LABORATORY

NAME :

REGISTER NO :

VM NO : VM -

BRANCH : AI&DS

YEAR : II

SEMESTER : IV

DEPARTMENT OF ARTIFICIAL INTELLIGENCE & DATA SCIENCE


Vision

 To promote centre of excellence through effectual Teaching and Learning, imparting the contemporary knowledge
centric education through innovative research in multidisciplinary fields.
Mission

 To impart quality technical skills through practicing, knowledge updating in recent technology and produce
professionals with multidisciplinary and leadership skills.
 To promote innovative thinking for design and development of software products of varying complexity with
intelligence to fulfil the global standards and demands.
 To inculcate professional ethics among thegraduates and to adapt the changing technologies through lifelong learning.
An Autonomous Institution
Approved by AICTE, Affiliated to Anna University, Chennai.
ISO 9001:2015 Certified Institution, Accredited by NBA (BME, CSE, ECE, EEE, IT & MECH),
Accredited by NAAC.
#42, Avadi-Vel Tech Road, Avadi, Chennai- 600062, Tamil Nadu, India.

CERTIFICATE

Name …………………….………………Year: ……………… Semester:…………. Branch:


B.TECH – ARTIFICIAL INTELLIGENCE AND DATA SCIENCE University Register
No………………….. College Roll No:……………… Certified that this is the bonafide record of
work done by the above student in the 191CS42B– OPERATING SYSTEMS LABORATORY during
the academic year 2023-2024.

Signature of the Course In-charge Signature of Head of the Department

Submitted for the University Practical Examination held on ………………... at VEL TECH MULTI
TECH Dr.RANGARAJAN Dr.SAKUNTHALA ENGINEERING COLLEGE, No.42, AVADI –
VEL TECH ROAD, AVADI, CHENNAI-600062.

Signature of Examiners

Internal Examiner:…………… External Examiner:………………

Date:………………
DEPARTMENT OF ARTIFICIAL INTELLIGENCE AND DATA SCIENCE

POs Programme Outcomes (POs)

PO1 Engineering Knowledge: Apply knowledge of mathematics, science, engineering


fundamentals and an Engineering Specialization to the solution of complex engineering
problems.

PO2 Problem Analysis: Identify, formulate, review research literature and analyze complex
engineering problems reaching substantiated conclusions using first principles of mathematics,
natural sciences, and engineering sciences.

PO3 Design / Development of solutions: Design solutions for complex engineering problems and
design system components or processes that meet specified needs with appropriate consideration
for public health and safety, cultural, societal, and environmental considerations.

PO4 Conduct Investigations of Complex Problems: Use research-based knowledge and research
methods including design of experiments, analysis and interpretation of data, and synthesis of the
information to provide valid conclusions.

PO5 Modern tool usage: Create, select, and apply appropriate techniques, resources, and modern
engineering and IT tools including prediction and modeling to complex engineering activities
with an understanding of the limitations.

PO6 The Engineer and Society: Apply reasoning informed by the contextual knowledge to assess
societal, health, safety, legal and cultural issues and the consequent responsibilities relevant to
the professional engineering practice.

PO7 Environment and sustainability: Understand the impact of the professional engineering
solutions in societal and environmental contexts, and demonstrate the knowledge of, and need
for sustainable development.

PO8 Ethics: Apply ethical principles and commit to professional ethics and responsibilities and norms
of the engineering practice.

PO9 Individual and team work: Function effectively as an individual, and as a member or leader in
diverse teams, and in multidisciplinary settings.

PO10 Communication: Communicate effectively on complex engineering activities with the


engineering community and with society at large, such as, being able to comprehend and write
effective reports and design documentation, make effective presentations, and give and receive
clear instructions

PO11 Project Management and Finance: Demonstrate knowledge and understanding of the
engineering and management principles and apply these to one’s own work, as a member and
leader in a team, to manage projects and in multidisciplinary environments.

PO12 Life-long learning: Recognize the need for, and have the preparation and ability to engage in
independent and life-long learning in the broadest context of technological change.
PROGRAM EDUCATIONAL OBJECTIVES(PEOs)

PEOs Programme Educational Objectives(PEOs)

Train the graduates with the potential of strong knowledge in the respective field and to create
PEO1
innovative multidisciplinary solutions for challenges in the society.

Groom the engineers to understand, analyse different nature of data and use Machine Learning
PEO2 techniques to develop software systems with varying complexity for data intensive
applications.

To practice professionalism among the graduates and reflect good leadership skills with ethical
PEO3
standards and continued professional development through lifelong learning.

PROGRAMMESPECIFICOUTCOMES(PSOs)

PSO’s PROGRAMMESPECIFICOUTCOMES(PSOs)

To impart theoretical knowledge in the respective field along with recent industrial tools
PSO1
and techniques to solve societal problems

Apply the core competency obtained in the field of MachineLearning for analysis,design
PSO2
and development of computing systems formulti-disciplinary problems

Acquire knowledge in the field of intelligence,deep learning and develop software


PSO3
solutions for security and analytics of large volume of data.
COURSE OBJECTIVES

The student should be made to:

 To learn Unix commands and shell programming.


 To implement various CPU Scheduling Algorithms.
 To implement Process Creation and Inter Process Communication.
 To implement Deadlock Avoidance and Deadlock Detection Algorithms.
 To implement Page Replacement Algorithms.
 To implement File Organization and File Allocation Strategies

COURSE OUTCOMES
At the end of the course, the student should be able to

Course CO Statements
Outcome

CO1 Write functions to implement linear and non-linear data structure operations.
Suggest appropriate linear / non-linear data structure operations for solving a given
CO2
problem
CO3 Appropriately use the linear / non-linear data operations for a given problem
Apply appropriate hash functions that result in a collision free scenario for data storage
CO4
and retrieval
CO5 Apply appropriate sorting and searching functions based on the application.

CO – PO MAPPING

CO PO 1 PO 2 PO 3 PO 4 PO 5 PO 6 PO 7 PO 8 PO 9 PO10 PO11 PO12


CO1 3 3 3 2 2 2 2 2 2 2 2 2

CO2 3 3 3 2 2 2 2 2 2 2 2 2

CO3 3 3 3 2 2 2 2 2 2 2 2 2

CO4 3 3 3 2 2 2 2 2 2 2 2 2

CO5 3 3 3 2 2 2 2 2 2 2 2 2

CO 3 3 3 2 2 2 2 2 2 2 2 2
LIST OF EXPERIMENTS

EX.NO DATE NAME OF THE EXERCISE PAGE NO MARKS SIGN

1 BASIC UNIX COMMANDS


SYSTEM CALLS OF UNIX OPERATING SYSTEMS
2. FORK,EXEC,GETPID,EXIT,WAIT,CLOSE,STAT,OPENDI
R, READDIR

3 SIMULATE UNIX COMMANDS LIKE CP,LS,GREP etc

4 SHELL PROGRAMMING

WRITE A C PROGRAMMING TO IMPLEMENT VARIOUS


5 CPU SCHEDULING ALGORITHMS

6 SEMAPHORE IMPLEMENTATION

7 IMPLEMENTATION OF SHARED MEMORY AND IPC

8 BANKERS ALGORITHM FOR DEADLOCK AVOIDANCE

9 DEADLOCK DETECTION ALGORITHM

10 THREADING AND SYNCHRONIZATION


MEMORY ALLOCATION METHOD FOR FIXED
11
PARTITION

12 PAGING TECHNIQUE FOR MEMORY MANAGEMENT

13 PAGE REPLACEMENTALGORITHMS

14 FILE ORGANIZATION TECHNIQUES

15 FILE ALLOCATION STRATEGY


EX.No:1 DATE:
BASIC UNIX COMMANDS
AIM
To study and execute Unix commands.
LOGIN
Typetelnetserver_ipaddress in run window.
User has to authenticate himself by providing username and password. Once verified, a
greeting and $ prompt appears. The shell is now ready to receive commands from the
user. Options suffixed with a hyphen (–) and arguments are separated by space
GENERAL COMMANDS

Command Function

Date Used to display the current system date and time.

date + %D Displays date only

date + %T Displays time only

date + %Y Displays the year part of date

date + %H Displays the hour part of time

Cal Calendar of the current month

Cal year Displays calendar for all months of the specified year

Cal month year Displays calendar for the specified month of the year

Who Login details of all users such as their IP, Terminal No, User
name

Who am i Used to display the login details of the user

Uname Displays the Operating System

Uname -r Shows version number of the OS (kernel)

Uname -n Displays domain name of the server

Echo $HOME Displays the user's home directory

Bc Basic calculator. Press Ctrl+d to quit

lp file Allows the user to spool a job along with others in a print queue.
man cmdname Manual for the given command. Press q to exit

History To display the commands used by the user since log on

Exit Exit from a process. If shell is the only process then logs out

DIRECTORY COMMANDS

Command Function

Pwd Path of the present working directory

Mkdirdir A directory is created in the given name under the current directory

mkdir A number of sub-directories can be created under one stroke

cd subdir Change Directory. If the subdir starts with / then path starts from
root (absolute) otherwise from current working directory

cd To switch to the home directory.

cd / To switch to the root directory

cd .. To move back to the parent directory

rmdir subdir Removes an empty sub-directory.

FILE COMMANDS

Command Function

cat > filename To create a file with some contents. To end typing press Ctrl+d.
The > symbol means redirecting output to a file. (< for input)

cat filename Displays the file contents.

cat >> filename Used to append contents to a file

cp srcdes Copy files to given location. If already exists, it will be


overwritten

cp –isrc des Warns the user prior to overwriting the destination file

cp –r src des Copies the entire directory, all its sub-directories and files.

mv old new To rename an existing file or directory. –i option can also be used

mv f1 f2 f3 dir To move a group of files to a directory.

mv –v old new Display name of each file as it is moved.


rm file Used to delete a file or group of files. –i option can also be used

rm * To delete all the files in the directory.

rm –r * Deletes all files and sub-directories

rm –f * To forcibly remove even write-protected files

Ls Lists all files and subdirectories (blue colored) in sorted manner.

ls name To check whether a file or directory exists.

ls name* Short-hand notation to list out filenames of a specific pattern.

ls –a Lists all files including hidden files (files beginning with .)

ls –x dirname To have specific listing of a directory

ls –R Recursive listing of all files in the subdirectories

ls –l Long listing showing file access rights (read/write/execute-rwx for


user/group/others-ugo).

cmp file1 file2 Used to compare two files. Displays nothing if files are identical.

wc file It produces a statistics of lines (l), words(w), and characters(c).

chmod perm file Changes permission for the specified file. (r=4, w=2, x=1) chmod
740 file sets all rights for user, read only for groups and no rights
for others

The commands can be combined using the pipeline (|) operator. For example, number of
users logged in can be obtained as.
who | wc -l
Finally to terminate the unix session execute the command exit or logout
OUTPUT:

RESULT:

INFERENCE:
EX. No:2 DATE:

SYSTEM CALLS OF UNIX OPERATING SYSTEMS


FORK,EXEC,GETPID,EXIT,WAIT,CLOSE,STAT,OPENDIR, READDIR
AIM:
To create a new system calls of unix operating systems fork,exec,getpid,
exit,wait,close,stat,opendir, readdir
fork():
 The fork system call is used to create a new process called child process.
 The return value is 0 for a child process.
 The return value is negative if process creation is unsuccessful.
 For the parent process, return value is positive
 The child process is an exact copy of the parent process.
 Both the child and parent continue to execute the instructions following fork call.
 The child can start execution before the parent or vice-versa.
getpid() and getppid():
 The getpid system call returns process ID of the calling process.
 The getppid system call returns parent process ID of the calling process
ALGORITHM
STEP 1: Declare a variable x to be shared by both child and parent.
STEP 2: Create a child process using fork system call.
STEP 3: If return value is -1 then
i)Print "Process creation unsuccessfull"
ii)Terminate using exit system call.
STEP 4: If return value is 0 then Print "Child process" Print process id of the child using
getpid system call Print value of x Print process id of the parent using getppid system
call 5:
STEP 5: Otherwise
i)Print "Parent process"
ii)Print process id of the parent using getpid system call
iii)Print value of x
iv)Print process id of the shell using getppid system call.
STEP 6: Stop the program.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
main()
{
pid_tpid;
int x = 5;
pid = fork();
x++;
if (pid< 0)
{
printf("Process creation error");
exit(-1);
}
else if (pid == 0)
{
printf("Child process:");
printf("\nProcess id is %d", getpid());
printf("\nValue of x is %d", x);
printf("\nProcess id of parent is %d\n", getppid());
}
else
{
printf("\nParent process:");
printf("\nProcess id is %d", getpid());
printf("\nValue of x is %d", x);
printf("\nProcess id of shell is %d\n", getppid());
}
}

OUTPUT:
wait()
 The wait system call causes the parent process to be blocked until a child
terminates.
 When a process terminates, the kernel notifies the parent by sending the
SIGCHLD signal to
the parent.
 Without wait, the parent may finish first leaving a zombie child, to be adopted by
init
process
ALGORITHM
STEP 1: Create a child process using fork system call.
STEP 2: If return value is -1 then a. Print "Process creation unsuccessfull"
STEP 3: Terminate using exit system call.
STEP 4: If return value is > 0 then
i)Suspend parent process until child completes using wait system call
ii)Print "Parent starts"
iii)Print even numbers from 0–10 d. Print "Parent ends"
STEP 5: If return value is 0 then
i) Print "Child starts"
ii)Print odd numbers from 0–10
iii)Print "Child ends"
STEP 6: Stop the program.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
main()
{
int i, status;
pid_tpid;
pid = fork();
if (pid< 0)
{
printf("\nProcess creation failure\n");
exit(-1);
}
else if(pid> 0)
{
wait(NULL);
printf ("\nParent starts\nEven Nos: ");
for (i=2;i<=10;i+=2)
printf ("%3d",i);
printf ("\nParent ends\n");
}
else if (pid == 0)
{
printf ("Child starts\nOdd Nos: ");
for (i=1;i<10;i+=2)
printf ("%3d",i);
printf ("\nChild ends\n");
}
}

OUTPUT:
execl()
 The exec family of function (execl, execv, execle, execve, execlp, execvp) is
used by the child process to load a program and execute.
 execl system call requires path, program name and null point
ALGORITHM
STEP 1: Create a child process using fork system call.
STEP 2: If return value is -1 then a. Print "Process creation unsuccessfull"
STEP 3: Terminate using exit system call.
STEP 4: If return value is > 0 then
i) Suspend parent process until child completes using wait system call
ii) Print "Parent starts"
iii) Print even numbers from 0–10 d. Print "Parent ends"
STEP 5: If return value is 0 then
i) Print "Child starts"
ii) Print odd numbers from 0–10
iii) Print "Child ends"
STEP 6: Stop the program.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
main()
{
pid_tpid;
switch(pid = fork())
{
case -1:
perror("Fork failed");
exit(-1);
case 0:
printf("Child process\n");
execl("/bin/date", "date", 0);
exit(0);
default:
wait(NULL);
printf("Child Terminated\n");
exit(0);
}}
OUTPUT:

exit()
 The exit system call is used to terminate a process either normally or
abnormally
 Closes all standard I/O streams.
stat()
 The stat system call is used to return information about a file as a structure.

ALGORITHM
STEP 1: Get filename as command line argument.
STEP 2: If filename does not exist then stop.
STEP 3: Call stat system call on the filename that returns a structure
STEP 4: Display members st_uid, st_gid, st_blksize, st_block, st_size, st_nlink, etc.,
STEP 5: Convert time members such as st_atime, st_mtime into time using
ctimefunction
STEP 6: Compare st_mode with mode constants such as S_IRUSR, S_IWGRP,
S_IXOTH and display file permissions.
STEP 7: Stop the program.
PROGRAM
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char*argv[])
{
struct stat file;
int n;
if (argc != 2)
{
printf("Usage: ./a.out<filename>\n");
exit(-1);
}
if ((n = stat(argv[1], &file)) == -1)
{
perror(argv[1]);
exit(-1);
}
printf("User id : %d\n", file.st_uid);
printf("Group id : %d\n", file.st_gid);
printf("Block size : %d\n", file.st_blksize);
printf("Blocks allocated : %d\n", file.st_blocks);
printf("Inode no. : %d\n", file.st_ino);
printf("Last accessed : %s", ctime(&(file.st_atime)));
printf("Last modified : %s", ctime(&(file.st_mtime)));
printf("File size : %d bytes\n", file.st_size);
printf("No. of links : %d\n", file.st_nlink);
printf("Permissions : ");
printf( (S_ISDIR(file.st_mode)) ? "d" : "-");
printf( (file.st_mode& S_IRUSR) ? "r" : "-");
printf( (file.st_mode& S_IWUSR) ? "w" : "-");
printf( (file.st_mode& S_IXUSR) ? "x" : "-");
printf( (file.st_mode& S_IRGRP) ? "r" : "-");
printf( (file.st_mode& S_IWGRP) ? "w" : "-");
printf( (file.st_mode& S_IXGRP) ? "x" : "-");
printf( (file.st_mode& S_IROTH) ? "r" : "-");
printf( (file.st_mode& S_IWOTH) ? "w" : "-");
printf( (file.st_mode& S_IXOTH) ? "x" : "-");
printf("\n");
if(file.st_mode& S_IFREG)
printf("File type : Regular\n");
if(file.st_mode& S_IFDIR)
printf("File type : Directory\n");
}
OUTPUT:

opendir( ) ,readdir( ) and closedir( )


 The opendir system call is used to open a directory
a. It returns a pointer to the first entry
b. It returns NULL on error.
 The readdir system call is used to read a directory as a direntstructure
a. It returns a pointer pointing to the next entry in directory stream
b. It returns NULL if an error or end-of-file occurs.
 The closedir system call is used to close the directory stream
 Write to a directory is done only by the kernel.

ALGORITHM
STEP 1: Get directory name as command line argument.
STEP 2: If directory does not exist then stop.
STEP 3: Open the directory using opendir system call that returns a structure
STEP 4: Read the directory using readdir system call that returns a structure
STEP 5: Display d_name member for each entry.
STEP 6: Close the directory using closedir system call.
STEP 7: Stop the program.

PROGRAM
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
struct dirent *dptr;
DIR *dname;
if (argc != 2)
{
printf("Usage: ./a.out<dirname>\n");
exit(-1);
}
if((dname = opendir(argv[1])) == NULL)
{
perror(argv[1]);
exit(-1);
}
while(dptr=readdir(dname))
printf("%s\n", dptr->d_name);
closedir(dname);
}

OUTPUT:

open()
 Used to open an existing file for reading/writing or to create a new file.
 Returns a file descriptor whose value is negative on error.
 The mandatory flags are O_RDONLY, O_WRONLY and O_RDWR
 Optional flags include O_APPEND, O_CREAT, O_TRUNC, etc
 The flags are ORed.
 The mode specifies permissions for the file
creat()
 Used to create a new file and open it for writing.
 It is replaced with open() with flags O_WRONLY|O_CREAT | O_TRUNC

ALGORITHM
STEP 1: Declare a character buffer buf to store 100 bytes.
STEP 2: Get the new filename as command line argument.
STEP 3: Create a file with the given name using open system call with O_CREAT
and O_TRUNCoptions.
STEP 4: Check the file descriptor.
a) If file creation is unsuccessful, then stop.
STEP 5: Get input from the console until user typesCtrl+D
a) Read 100 bytes (max.) from console and store onto buf using read system
call
b) Write length of buf onto file using write system call.
STEP 6: Close the file using close system call.
STEP 7: Stop the program.

PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd, n, len;
char buf[100];
if (argc != 2)
{
printf("Usage: ./a.out<filename>\n");
exit(-1);
}
fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
if(fd< 0)
{
printf("File creation problem\n");
exit(-1);
}

printf("Press Ctrl+D at end in a new line:\n");


while((n = read(0, buf, sizeof(buf))) > 0)
{
len = strlen(buf);
write(fd, buf, len);
}
close(fd);
}
OUTPUT:

read()
 Reads no. of bytes from the file or from the terminal.
 If read is successful, it returns no. of bytes read.
 The file offset is incremented by no. of bytes read.
 If end-of-file is encountered, it returns 0.
ALGORITHM
STEP 1: Declare a character buffer buf to store 100 bytes.
STEP 2: Get existing filename as command line argument.
STEP 3: Open the file for reading using open system call with O_RDONLY option.
STEP 4: Check the file descriptor.
a) If file does not exist, then stop.
STEP 5: Read until end-of-file using read system call.
a) Read 100 bytes (max.) from file and print it
STEP 6: Close the file using close system call.
STEP 7: Stop the program.

PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd,i;
char buf[100];
if (argc< 2)
{
printf("Usage: ./a.out<filename>\n");
exit(-1);
}
fd = open(argv[1], O_RDONLY);
if(fd == -1)
{
printf("%s file does not exist\n", argv[1]);
exit(-1);
}
printf("Contents of the file %s is : \n", argv[1]);
while(read(fd, buf, sizeof(buf)) > 0)
printf("%s", buf);
close(fd);
}

OUTPUT:

write( )
 Writes no. of bytes onto the file.
 After a successful write, file's offset is incremented by the no. of bytes
written.
 If any error due to insufficient storage space, write fails.
close( )
 Closes a opened file.
 When process terminates, files associated with the process are automatically
closed.

ALGORITHM
STEP 1: Declare a character buffer buf to store 100 bytes.
STEP 2: Get exisiting filename as command line argument.
STEP 3: Create a file with the given name using open system call with O_APPEND
option.
STEP 4: Check the file descriptor.
a) If value is negative, then stop.
STEP 5: Get input from the console until user typesCtrl+D
a) Read 100 bytes (max.) from console and store onto buf using read system
call
b) Write length of buf onto file using write system call.
STEP 6: Close the file using close system call.
STEP 7: Stop the program.

PROGRAM
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd, n, len;
char buf[100];
if (argc != 2)
{
printf("Usage: ./a.out<filename>\n");
exit(-1);
}
fd = open(argv[1], O_APPEND|O_WRONLY|O_CREAT, 0644);
if (fd< 0)
{
perror(argv[1]);
exit(-1);
}
while((n = read(0, buf, sizeof(buf))) > 0)
{
len = strlen(buf);
write(fd, buf, len);
}
close(fd);
}
OUTPUT:

RESULT:

INFERENCE:
EX.No:3 DATE:
SIMULATE UNIX COMMANDS LIKE CP,LS,GREP
AIM
To simulate unix commands like cp,ls,grep.

ALGORITHM
STEP 1: Store path of current working directory using getcwd system call.
STEP 2: Scan directory of the stored path using scandir system call and sort the
resultant array of
structure.
STEP 3: Display dname member for all entries if it is not a hidden file.
STEP 4: Stop the program.

PROGRAM
#include <stdio.h>
#include <dirent.h>
main()
{
struct dirent **namelist;
int n,i;
char pathname[100];
getcwd(pathname);
n = scandir(pathname, &namelist, 0, alphasort);
if(n < 0)
printf("Error\n");
else
for(i=0; i<n; i++)
if(namelist[i]->d_name[0] != '.')
printf("%-20s", namelist[i]->d_name);
}
OUTPUT:

GREP COMMAND
ALGORITHM:
STEP 1: Get filename and search string as command-line argument.
STEP 2: Open the file in read-only mode using open system call.
STEP 3: If file does not exist, then stop.
STEP 4: Let length of the search string be n.
STEP 5: Read line-by-line until end-of-file
a. Check to find out the occurrence of the search string in a line by examining
characters in
the range 1–n, 2–n+1, etc.
b. If search string exists, then print the line.
STEP 6: Close the file using close system call.
STEP 7: Stop.

PROGRAM
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
main(int argc,char *argv[])
{
FILE *fd;
char str[100];
char c;
int i, flag, j, m, k;
char temp[30];
if(argc != 3)
{
printf("Usage: gccmygrep.c –o mygrep\n");
printf("Usage: ./mygrep<search_text><filename>\n");
exit(-1);
}
fd = fopen(argv[2],"r");
if(fd == NULL)
{
printf("%s is not exist\n",argv[2]);
exit(-1);
}
while(!feof(fd))
{
i = 0;
while(1)
{
c = fgetc(fd);
if(feof(fd))
{
str[i++] = '\0';
break;
}
if(c == '\n')
{
str[i++] = '\0';
break;
}
str[i++] = c;
}
if(strlen(str) >= strlen(argv[1]))
for(k=0; k<=strlen(str)-strlen(argv[1]); k++)
{
for(m=0; m<strlen(argv[1]); m++)
temp[m] = str[k+m];
temp[m] = '\0';
if(strcmp(temp,argv[1]) == 0)
{
printf("%s\n",str);
break;}}}}

OUTPUT:

CP COMMAND
ALGORITHM
STEP 1: Get source and destination filename as command-line argument.
STEP 2: Declare a buffer of size 1KB
STEP 3: Open the source file in readonly mode using open system call.
STEP 4: If file does not exist, then stop.
STEP 5: Create the destination file using creat system call.
STEP 6: If file cannot be created, then stop.
STEP 7: File copy is achieved as follows:
a. Read 1KB data from source file and store onto buffer using read system
call.
b. Write the buffer contents onto destination file using write system call.
c. If end-of-file then step 8 else step 7a.
STEP 8: Close source and destination file using close system call.
STEP 9: Stop.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define SIZE 1024
main(int argc, char *argv[])
{
int src, dst, nread;
char buf[SIZE];
if (argc != 3)
{
printf("Usage: gcccopy.c -o copy\n");
printf("Usage: ./copy <filename><newfile> \n");
exit(-1);
}
if ((src = open(argv[1], O_RDONLY)) == -1)
{
perror(argv[1]);
exit(-1);
}
if ((dst = creat(argv[2], 0644)) == -1)
{
perror(argv[1]);
exit(-1);
}
while ((nread = read(src, buf, SIZE)) > 0)
{
if (write(dst, buf, nread) == -1)
{
printf("can't write\n");
exit(-1);
}
}
close(src);
close(dst);
}
OUTPUT:

RM COMMAND
ALGORITHM
STEP 1: Get filename as command-line argument.
STEP 2: Open the file in read-only mode using read system call.
STEP 3: If file does not exist, then stop.
STEP 4: Close the file using close system call.
STEP 5: Delete the file using unlink system call.
STEP 6: Stop.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
main(int argc, char* argv[])
{
int fd;
if (argc != 2)
{
printf("Usage: gccdel.c -o del\n");
printf("Usage: ./del <filename>\n");
exit(-1);
}
fd = open(argv[1], O_RDONLY);
if (fd != -1)
{
close(fd);
unlink(argv[1]);
}
else
perror(argv[1]);
}

OUTPUT:

RESULT:

INFERENCE:
EX.No:4 DATE:
SHELL PROGRAMMING

AIM
To write simple shell scripts using shell programming fundamentals.
The activities of a shell are not restricted to command interpretation alone. The shell
also has rudimentary programming features. Shell programs are stored in a file (with
extension .sh). Shell programs run in interpretive mode. The original UNIX came with
the Bourne shell (sh) and it is universal even today. C shell (csh) and Korn shell (ksh)
are also widely used. Linux offers Bash shell (bash) as a superior alternative to Bourne
shell.

PRELIMINARIES
STEP 1: Comments in shell script start with #.
STEP 2: Shell variables are loosely typed i.e. not declared. Variables in an
expression or output must be prefixed by $.
STEP 3: The read statement is shell's internal tool for making scripts interactive.
STEP 4: Output is displayed using echo statement.
STEP 5: Expressions are computed using the expr command. Arithmetic operators
are + - * / %. Meta characters * ( ) should be escaped with a \.
STEP 6: The shell scripts are executed
i) $ sh filename
Decision-making
Shell supports decision-making using if statement. The if statement like its
counterpart in programming languages has the following formats.

if [ condition ] if [ condition ] if [condition ]


then then then
statements statements statements
fi else elif [ condition ]
statements then
fi statements
.. .
else
statements
fi

The set of relational operators are –eq –ne –gt –ge –lt –le and logical operators used in
conditional expression are –a –o !
Multi-way branching
The case statement is used to compare a variables value against a set of constants. If it
matches a constant, then the set of statements followed after ) is executed till a ;; is
encountered. The optional default block is indicated by *. Multiple constants can be
specified in a single pattern separated by |.

case variable in
constant1)
statements ;;
constant2)
statements ;;
...
*)
statements
esac

Loops
Shell supports a set of loops such as for, while and until to execute a set of
statements repeatedly. The body of the loop is contained between do and done
statement.
The for loop doesn't test a condition, but uses a list instead.

for variable in list


do
statements
done

The while loop executes the statements as long as the condition remains true. while [
condition ] do statements done The until loop complements the while construct in the
sense that the statements are executed as long as the condition remains false.

until [ condition ]
do
statements
done
A) SWAPPING VALUES OF TWO VARIABLES
echo -n "Enter value for A:"
read a
echo -n "Enter value for B:"
read b
t=$a
a=$b
b=$t
echo "A value is $a and B value is $b"
Output

B) Farenheit to Centigrade Conversion


# Degree conversion – degconv.sh

echo -n "Enter Fahrenheit : "

read f

c=`expr \( $f - 32 \) \* 5 / 9`

echo "Centigrade is : $c"

Output

C) Biggest of 3 numbers
# Biggest – big3:sh
echo -n "Give value for A B and C: "
read a b c
if [ $a -gt $b -a $a -gt $c ]
then
echo "A is the Biggest number"
elif [ $b -gt $c ]
then
echo "B is the Biggest number"
else echo "C is the Biggest number"
fi

Output

D) Grade Determination
# Grade – grade.sh
echo -n "Enter the mark : "
read mark
if [ $mark -gt90 ]
then
echo "S Grade"
elif [ $mark -gt80 ]
then
echo "A Grade"
elif [ $mark -gt70 ]
then
echo "B Grade"
elif [ $mark -gt60 ]
then
echo "C Grade"
elif [ $mark -gt55 ]

then

echo "D Grade"

elif [ $mark -ge50 ]

then

echo "E Grade"

else

echo "U Grade"

fi
Output

E) Vowel or Consonant
# Vowel - vowel.sh
echo -n "Key in a lower case character : "
read choice
case $choice in
a|e|i|o|u) echo "It's a Vowel";;
*) echo "It's a Consonant"
esac

Output

F) Simple Calculator
# Arithmetic operations — calc.sh
echo -n "Enter the two numbers : "
read a b
echo " 1: Addition"
echo " 2: Subtraction"
echo " 3: Multiplication"
echo " 4: Division"
echo -n "Enter the option : "
read option
case $option in
1) c=`expr $a + $b`
echo "$a + $b = $c";;
2) c=`expr $a - $b`
echo "$a - $b = $c";;

3) c=`expr $a \* $b`
echo "$a * $b = $c";;
4) c=`expr $a / $b`
echo "$a / $b = $c";;
*) echo "Invalid Option"

esac

Output

G) Multiplication Table
# Multiplication table – multable.sh
clear
echo -n "Which multiplication table? : "
read n
for x in 1 2 3 4 5 6 7 8 9 10
do
p=`expr $x \* $n`
echo -n "$n X $x = $p"
sleep 1
done

Output

H) Number Reverse
# To reverse a number – reverse.sh
echo -n "Enter a number : "
read n
rd=0
while [ $n -gt0 ]
do
rem=`expr $n % 10`
rd=`expr $rd \* 10 + $rem`
n=`expr $n / 10`
done
echo "Reversed number is $rd"

Output

I) Prime Number
# Prime number – prime.sh
echo -n "Enter the number : "
read n
i=2
m=`expr $n / 2`
until [ $i -gt $m ]
do
q=`expr $n % $i`
if [ $q -eq0 ]
then
echo "Not a Prime number"
exit
fi
i=`expr $i + 1`
done

echo "Prime number"


OUTPUT:

RESULT:

INFERENCE:
EX. NO:5 DATE:

IMPLEMENT VARIOUS CPU SCHEDULING ALGORITHMS


AIM
To schedule implement various cpu scheduling algorithms programmed operating
systems.
 By switching CPU among processes, efficiency of the system can be
improved.
 Some scheduling algorithms are FCFS, SJF, Priority, Round-Robin, etc.
 Gantt chart provides a way of visualizing CPU scheduling and enables to
understand better.
First Come First Serve (FCFS)
ALGORITHM
STEP 1: Define an array of structure process with members pid, btime,
wtime&ttime.
STEP 2: Get length of the ready queue, i.e., number of process (say n)
STEP 3: Obtain btime for each process.
STEP 4: The wtime for first process is 0.
STEP 5: Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei
STEP 6: Compute average waiting time awat and average turnaround time atur
STEP 7: Display the btime, ttime and wtime for each process.
STEP 8: Display GANTT chart for the above scheduling
STEP 9: Display awat time and atur
STEP 10: Stop

PROGRAM
struct process
{
int pid;
int btime;
int wtime;
int ttime;
} p[10];
main()
{
int i,j,k,n,ttur,twat;
float awat,atur;
printf("Enter no. of process : ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ",(i+1));
scanf("%d", &p[i].btime);
p[i].pid = i+1;
}
p[0].wtime = 0;
for(i=0; i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime;
p[i].ttime = p[i].wtime + p[i].btime;
}
ttur = twat = 0;
for(i=0; i<n; i++)
{
ttur += p[i].ttime;
twat += p[i].wtime;
}
awat = (float)twat / n;
atur = (float)ttur / n;
printf("\n FCFS Scheduling\n\n");
for(i=0; i<28; i++)
printf("-");
printf("\nProcess B-Time T-Time W-Time\n");
for(i=0; i<28; i++)
printf("-");
for(i=0; i<n; i++)
printf("\n P%d\t%4d\t%3d\t%2d",
p[i].pid,p[i].btime,p[i].ttime,p[i].wtime);
printf("\n");
for(i=0; i<28; i++)
printf("-");
printf("\n\nAverage waiting time : %5:2fms", awat);
printf("\nAverageturn around time : %5:2fms\n", atur);
printf("\n\nGANTT Chart\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n");
printf("|");
for(i=0; i<n; i++)
{
k = p[i].btime/2;
for(j=0; j<k; j++)
printf(" ");
printf("P%d",p[i].pid);
for(j=k+1; j<p[i].btime; j++)
printf(" ");
printf("|");
}
printf("\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n");
printf("0");
for(i=0; i<n; i++)
{
for(j=0; j<p[i].btime; j++)
printf(" ");
printf("%2d",p[i].ttime);
}
}
OUTPUT:

Shortest Job First (SJF)


 Process that requires smallest burst time is processed first.
 SJF can be preemptive or non–preemptive
 When two processes require same amount of CPU utilization, FCFS is used to
break the tie.
 Generally efficient as it results in minimal average waiting time.
 Can result in starvation, since long critical processes may not be processed.

ALGORITHM
STEP 1: Define an array of structure process with members pid, btime,
wtime&ttime.
STEP 2: Get length of the ready queue, i.e., number of process (say n)
STEP 3: Obtain btime for each process.
STEP 4: Sort the processes according to their btime in ascending order. a. If two
process have same btime, then FCFS is used to resolve the tie.
STEP 5: The wtime for first process is 0.
STEP 6: Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei
STEP 7: Compute average waiting time awat and average turn around time atur.
STEP 8: Display btime, ttime and wtime for each process.
STEP 9: Display GANTT chart for the above scheduling
STEP 10: Display awat and atur
STEP 11: Stop
PROGRAM
#include <stdio.h>
struct process
{
int pid;
int btime;
int wtime;
int ttime;
} p[10], temp;
main()
{
int i,j,k,n,ttur,twat;
float awat,atur;
printf("Enter no. of process : ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ",(i+1));
scanf("%d", &p[i].btime);
p[i].pid = i+1;
}
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if((p[i].btime> p[j].btime) ||
(p[i].btime == p[j].btime&& p[i].pid> p[j].pid))
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
p[0].wtime = 0;
for(i=0; i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime;
p[i].ttime = p[i].wtime + p[i].btime;
}
ttur = twat = 0;
for(i=0; i<n; i++)
{
ttur += p[i].ttime;
twat += p[i].wtime;
}
awat = (float)twat / n;
atur = (float)ttur / n;
printf("\n SJF Scheduling\n\n");
for(i=0; i<28; i++)
printf("-");
printf("\nProcess B-Time T-Time W-Time\n");
for(i=0; i<28; i++)
printf("-");
for(i=0; i<n; i++)
printf("\n P%-4d\t%4d\t%3d\t%2d",
p[i].pid,p[i].btime,p[i].ttime,p[i].wtime);
printf("\n");
for(i=0; i<28; i++)
printf("-");
printf("\n\nAverage waiting time : %5:2fms", awat);
printf("\nAverageturn around time : %5:2fms\n", atur);
printf("\n\nGANTT Chart\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n|");
for(i=0; i<n; i++)
{
k = p[i].btime/2;
for(j=0; j<k; j++)
printf(" ");
printf("P%d",p[i].pid);
for(j=k+1; j<p[i].btime; j++)
printf(" ");
printf("|");
}
printf("\n-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n0");
for(i=0; i<n; i++)
{
for(j=0; j<p[i].btime; j++)
printf(" ");
printf("%2d",p[i].ttime);
}
}
OUTPUT

PRIORITY SCHEDULING
 Process that has higher priority is processed first.
 Prioirty can be preemptive or non–preemptive
 When two processes have same priority, FCFS is used to break the tie.
 Can result in starvation, since low priority processes may not be processed.

ALGORITHM
STEP 1: Define an array of structure process with members pid, btime, pri,
wtime&ttime.
STEP 2: Get length of the ready queue, i.e., number of process (say n)
STEP 3: Obtain btime and pri for each process.
STEP 4: Sort the processes according to their pri in ascending order.
a. If two process have same pri, then FCFS is used to resolve the tie.
STEP 5: The wtime for first process is 0.
STEP 6: Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei
STEP 7: Compute average waiting time awat and average turn around time atur
STEP 8: Display the btime, pri, ttime and wtime for each process.
STEP 9: Display GANTT chart for the above scheduling
STEP 10: Display awat and atur
STEP 11: Stop
PROGRAM
#include <stdio.h>
struct process
{
int pid;
int btime;
int pri;
int wtime;
int ttime;
} p[10], temp;
main()
{
int i,j,k,n,ttur,twat;
float awat,atur;
printf("Enter no. of process : ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ", (i+1));
scanf("%d", &p[i].btime);
printf("Priority for process P%d : ", (i+1));
scanf("%d", &p[i].pri);
p[i].pid = i+1;
}
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if((p[i].pri> p[j].pri) ||
(p[i].pri == p[j].pri&& p[i].pid> p[j].pid) )
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}

}
}
p[0].wtime = 0;
for(i=0; i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime;
p[i].ttime = p[i].wtime + p[i].btime;
}
ttur = twat = 0;
for(i=0; i<n; i++)
{
ttur += p[i].ttime;
twat += p[i].wtime;
}
awat = (float)twat / n;
atur = (float)ttur / n;
printf("\n\t Priority Scheduling\n\n");
for(i=0; i<38; i++)
printf("-");
printf("\nProcess B-Time Priority T-Time W-Time\n");
for(i=0; i<38; i++)
printf("-");
for (i=0; i<n; i++)
printf("\n P%-4d\t%4d\t%3d\t%4d\t%4d",
p[i].pid,p[i].btime,p[i].pri,p[i].ttime,p[i].wtime);
printf("\n");
for(i=0; i<38; i++)
printf("-");
printf("\n\nAverage waiting time : %5:2fms", awat);
printf("\nAverageturn around time : %5:2fms\n", atur);

printf("\n\nGANTT Chart\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n|");
for(i=0; i<n; i++)
{
k = p[i].btime/2;
for(j=0; j<k; j++)
printf(" ");
printf("P%d",p[i].pid);
for(j=k+1; j<p[i].btime; j++)
printf(" ");
printf("|");
}
printf("\n-");
for(i=0; i<(p[n-1].ttime + 2*n); i++)
printf("-");
printf("\n0");
for(i=0; i<n; i++)
{
for(j=0; j<p[i].btime; j++)
printf(" ");
printf("%2d",p[i].ttime);
}
}

OUTPUT:
ROUND ROBIN SCHEDULING

 All processes are processed one by one as they have arrived, but in rounds.
 Each process cannot take more than the time slice per round.
 Round robin is a fair preemptive scheduling algorithm.
 A process that is yet to complete in a round is preempted after the time slice and
put at the end of the queue.
 When a process is completely processed, it is removed from the queue.

ALGORITHM
STEP 1: Get length of the ready queue, i.e., number of process (say n)
STEP 2: Obtain Burst time Bi for each processes Pi.
STEP 3: Get the time slice per round, say TS
STEP 4: Determine the number of rounds for each process.
STEP 5: The wait time for first process is 0.
STEP 6: If Bi > TS then process takes more than one round. Therefore turnaround
and waiting time should include the time spent for other remaining processes in the
same round.
STEP 7: Calculate average waiting time and turn aroundtime
STEP 8: Display the GANTT chart that includes
a. order in which the processes were processed in progression of rounds
b. Turnaround time Ti for each process in progression of rounds.
STEP 9: Display the burst time, turnaround time and wait time for each process (in
order of roundsthey were processed).
STEP 10: Display average wait time and turnaround time
STEP 11: Stop

PROGRAM
#include <stdio.h>
main()
{
int i,x=-1,k[10],m=0,n,t,s=0;
int a[50],temp,b[50],p[10],bur[10],bur1[10];
int wat[10],tur[10],ttur=0,twat=0,j=0;
float awat,atur;
printf("Enter no. of process : ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d : ", (i+1));
scanf("%d", &bur[i]);
bur1[i] = bur[i];
}
printf("Enter the time slice (in ms) : ");
scanf("%d", &t);
for(i=0; i<n; i++)
{
b[i] = bur[i] / t;
if((bur[i]%t) != 0)
b[i] += 1;
m += b[i];
}

printf("\n\t\tRound Robin Scheduling\n");


printf("\nGANTT Chart\n");
for(i=0; i<m; i++)
printf("--------");
printf("\n");
a[0] = 0;
while(j < m)
{
if(x == n-1)
x = 0;
else
x++;
if(bur[x] >= t)
{
bur[x] -= t;
a[j+1] = a[j] + t;
if(b[x] == 1)
{
p[s] = x;
k[s] = a[j+1];
s++;
}
j++;
b[x] -= 1;
printf(" P%d |", x+1);
}
else if(bur[x] != 0)
{
a[j+1] = a[j] + bur[x];
bur[x] = 0;
if(b[x] == 1)
{
p[s] = x;
k[s] = a[j+1];
s++;
}
j++;
b[x] -= 1;
printf(" P%d |",x+1);
}
}
printf("\n");
for(i=0;i<m;i++)
printf("--------");
printf("\n");
for(j=0; j<=m; j++)
printf("%d\t", a[j]);
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if(p[i] > p[j])
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
temp = k[i];
k[i] = k[j];
k[j] = temp;
}
}
}
for(i=0; i<n; i++)
{
wat[i] = k[i] - bur1[i];
tur[i] = k[i];
}
for(i=0; i<n; i++)
{
ttur += tur[i];
twat += wat[i];
}

printf("\n\n");
for(i=0; i<30; i++)
printf("-");
printf("\nProcess\tBurst\tTrnd\tWait\n");
for(i=0; i<30; i++)
printf("-");
for (i=0; i<n; i++)
printf("\nP%-4d\t%4d\t%4d\t%4d", p[i]+1, bur1[i],
tur[i],wat[i]);
printf("\n");
for(i=0; i<30; i++)
printf("-");
awat = (float)twat / n;
atur = (float)ttur / n;
printf("\n\nAverage waiting time : %.2f ms", awat);
printf("\nAverageturn around time : %.2f ms\n", atur);
}

OUTPUT:

RESULT:

INFERENCE:
EX.NO:6 DATE:
SEMAPHORE IMPLEMENTATION
AIM
To demonstrate the utility of semaphore in synchronization and multithreading.
Semaphore
 The POSIX system in Linux has its own built-in semaphore library.
 To use it, include semaphore.h. Compile the code by linking with -lpthread -lrt.
 To lock a semaphore or wait, use the sem_wait function.
 To release or signal a semaphore, use the sem_post function.
 A semaphore is initialised by using sem_init(for processes or threads)
 To declare a semaphore, the data type is sem_t..

ALGORITHM
STEP 1: 2 threads are being created, one 2 seconds after the first one.
STEP 2: But the first thread will sleep for 4 seconds after acquiring the lock.
STEP 3:Thus the second thread will not enter immediately after it is called, it will
enter 4 – 2 = 2 secs after it is called.
STEP 4: Stop

PROGRAM
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_tmutex;
void* thread(void* arg)
{
sem_wait(&mutex);
printf("\nEntered..\n");
sleep(4);
printf("\nJust Exiting...\n");
sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, 1);
pthread_t t1,t2;
pthread_create(&t1,NULL,thread,NULL);
sleep(2);
pthread_create(&t2,NULL,thread,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
sem_destroy(&mutex);
return 0;
}
OUTPUT:

RESULT:

INFERENCE:
EX.NO:7 DATE:
IMPLEMENTATION OF SHARED MEMORY AND IPC
AIM
To implementation of shared memory and ipc

ALGORITHM
STEP 1: Declare a array to store fibonacci numbers
STEP 2:Decalre a array pfd with two elements for pipe descriptors.
STEP 3: Create pipe on pfd using pipe function call.
a. If return value is -1 then stop
STEP 4: Using fork system call, create a child process.
STEP 5: Let the child process generate 25 fibonacci numbers and store them in a
array.
STEP 6: Write the array onto pipe using write system call.
STEP 7: Block the parent till child completes using wait system call.
STEP 8: Store fibonacci nos. written by child from the pipe in an array using read
system call
STEP 9: Inspect each element of the fibonacci array and check whether they are
prime
a. If prime then print the fibonacci term.
STEP 10: Stop

FIBONACCI NUMBERS

PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
main()
{
pid_tpid;
int pfd[2];
int i,j,flg,f1,f2,f3;
static unsigned int ar[25],br[25];
if(pipe(pfd) == -1)
{
printf("Error in pipe");
exit(-1);
}
pid=fork();
if (pid == 0)
{
printf("Child process generates Fibonacci series\n" );
f1 = -1;
f2 = 1;
for(i = 0;i < 25; i++)
{
f3 = f1 + f2;
printf("%d\t",f3);
f1 = f2;
f2 = f3;
ar[i] = f3;
}
write(pfd[1],ar,25*sizeof(int));
}
else if (pid> 0)
{
wait(NULL);
read(pfd[0], br, 25*sizeof(int));
printf("\nParent prints Fibonacci that are Prime\n");
for(i = 0;i < 25; i++)
{
flg = 0;
if (br[i] <= 1)
flg = 1;
for(j=2; j<=br[i]/2; j++)
{
if (br[i]%j == 0)
{
flg=1;
break;
}
}
if (flg == 0)
printf("%d\t", br[i]);
}
printf("\n");
}
else
{
printf("Process creation failed");
exit(-1);
}
}

OUTPUT:
WHO | WC -l

ALGORITHM
STEP 1:Decalre a array pfd with two elements for pipe descriptors.
STEP 2: Create pipe on pfd using pipe function call.
a. If return value is -1 then stop
STEP 3: Using fork system call, create a child process.
STEP 4: Free the standard output (1) using close system call to redirect the output to
pipe.
STEP 5: Make a copy of write end of the pipe using dup system call.
STEP 6: Execute who command using execlp system call.
STEP 7: Free the standard input (0) using close system call in the other process.
STEP 8: Make a close of read end of the pipe using dup system call.
STEP 9: Execute wc –l command using execlp system call.
STEP 10: Stop

PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pfds[2];
pipe(pfds);
if (!fork())
{
close(1);
dup(pfds[1]);
close(pfds[0]);
execlp("who", "who", NULL);
}
else
{
close(0);
dup(pfds[0]);
close(pfds[1]);
execlp("wc", "wc", "-l", NULL);
}
}

OUTPUT:

CHAT MESSAGING
ALGORITHM
SERVER
STEP 1:Decalre a structure mesgq with type and text fields.
STEP 2: Initialize key to 2013 (some random value).
STEP 3: Create a message queue using msgget with key & IPC_CREAT as
parameter.
a. If message queue cannot be created then stop.
STEP 4: Initialize the message type member of mesgq to 1:
STEP 5: Do the following until user typesCtrl+D
a. Get message from the user and store it in text member.
b. Delete the newline character in text member.
c. Place message on the queue using msgsend for the client to read.
d. Retrieve the response message from the client using msgrcvfunction
e. Display the text contents.
STEP 6: Remove message queue from the system using msgctl with IPC_RMID as
parameter.
STEP 7: Stop
CLIENT
STEP 1:Decalre a structure mesgq with type and text fields.
STEP 2: Initialize key to 2013 (same value as in server).
STEP 3: Open the message queue using msgget with key as parameter.
a. If message queue cannot be opened then stop.
STEP 4: Do while the message queue exists
a. Retrieve the response message from the server using msgrcvfunction
b. Display the text contents.
c. Get message from the user and store it in text member.
d. Delete the newline character in text member.
e. Place message on the queue using msgsend for the server to read.
STEP 5: Print "Server Disconnected".
STEP 6: Stop
PROGRAM
Server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct mesgq
{
long type;
char text[200];
} mq;
main()
{
int msqid, len;
key_t key = 2013;
if((msqid = msgget(key, 0644|IPC_CREAT)) == -1)
{
perror("msgget");
exit(1);
}

printf("Enter text, ^D to quit:\n");


mq.type = 1;
while(fgets(mq.text, sizeof(mq.text), stdin) != NULL)
{
len = strlen(mq.text);
if (mq.text[len-1] == '\n')
mq.text[len-1] = '\0';
msgsnd(msqid, &mq, len+1, 0);
msgrcv(msqid, &mq, sizeof(mq.text), 0, 0);
printf("From Client: \"%s\"\n", mq.text);
}
msgctl(msqid, IPC_RMID, NULL);
}
Client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct mesgq
{
long type;
char text[200];
} mq;
main()
{
int msqid, len;
key_t key = 2013;
if ((msqid = msgget(key, 0644)) == -1)
{
printf("Server not active\n");
exit(1);
}

printf("Client ready :\n");


while (msgrcv(msqid, &mq, sizeof(mq.text), 0, 0) != -1)
{
printf("From Server: \"%s\"\n", mq.text);

fgets(mq.text, sizeof(mq.text), stdin);


len = strlen(mq.text);
if (mq.text[len-1] == '\n')
mq.text[len-1] = '\0';
msgsnd(msqid, &mq, len+1, 0);
}
printf("Server Disconnected\n");
}

OUTPUT:

SHARED MEMORY
ALGORITHM
Server
STEP 1: Initialize size of shared memory shmsize to 27:
STEP 2: Initialize key to 2013 (some random value).
STEP 3: Create a shared memory segment using shmget with key & IPC_CREAT as
parameter.
a. If shared memory identifier shmid is -1, then stop.
STEP 4: Display shmid.
STEP 5: Attach server process to the shared memory using shmmat with shmid as
parameter.
a. If pointer to the shared memory is not obtained, then stop.
STEP 6: Clear contents of the shared region using memset function.
STEP 7: Write a–z onto the shared memory.
STEP 8: Wait till client reads the shared memory contents
STEP 9:Detatch process from the shared memory using shmdt system call.
STEP 10: Remove shared memory from the system using shmctl with IPC_RMID
argument
STEP 11: Stop

Client
1: Initialize size of shared memory shmsize to 27:
2: Initialize key to 2013 (same value as in server).
3: Obtain access to the same shared memory segment using same key.
a. If obtained then display the shmid else print "Server not started"
4: Attach client process to the shared memory using shmmat with shmid as
parameter.
a. If pointer to the shared memory is not obtained, then stop.
5: Read contents of shared memory and print it.
6: After reading, modify the first character of shared memory to '*'
7: Stop

PROGRAM
Server
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define shmsize 27

main()
{
char c;
int shmid;
key_t key = 2013;
char *shm, *s;

if ((shmid = shmget(key, shmsize, IPC_CREAT|0666)) < 0)


{
perror("shmget");
exit(1);
}
printf("Shared memory id : %d\n", shmid);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{
perror("shmat");
exit(1);
}
memset(shm, 0, shmsize);
s = shm;
printf("Writing (a-z) onto shared memory\n");
for (c = 'a'; c <= 'z'; c++)
*s++ = c;
*s = '\0';

while (*shm != '*');


printf("Client finished reading\n");
if(shmdt(shm) != 0)
fprintf(stderr, "Could not close memory segment.\n");
shmctl(shmid, IPC_RMID, 0);
}
Client
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define shmsize 27
main()
{
int shmid;
key_t key = 2013;
char *shm, *s;

if ((shmid = shmget(key, shmsize, 0666)) < 0)


{
printf("Server not started\n");
exit(1);
}
else
printf("Accessing shared memory id : %d\n",shmid);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{
perror("shmat");
exit(1);
}
printf("Shared memory contents:\n");
for (s = shm; *s != '\0'; s++)
putchar(*s);
putchar('\n');

*shm = '*';
}

OUTPUT:
PRODUCER CONSUMER PROBLEM
ALGORITHM
STEP 1: Create a shared memory segment BUFSIZE of size 1 and attach it.
STEP 2: Obtain semaphore id for variables empty, mutex and full using semget
function.
STEP 3: Create semaphore for empty, mutex and full as follows:
a. Declare semun, a union of specific commands.
b. The initial values are: 1 for mutex, N for empty and 0 for full
c. Use semctl function with SETVAL command
STEP 4: Create a child process using fork system call.
a. Make the parent process to be the producer
b. Make the child process to the consumer
STEP 5: The producer produces 5 items as follows:
a. Call wait operation on semaphores empty and mutex using semop function.
b. Gain access to buffer and produce data for consumption
c. Call signal operation on semaphores mutex and full using semop function.
STEP 6: The consumer consumes 5 items as follows:
a. Call wait operation on semaphores full and mutex using semop function.
b. Gain access to buffer and consume the available data.
c. Call signal operation on semaphores mutex and empty using semop
function.
STEP 7: Remove shared memory from the system using shmctl with IPC_RMID
argument
STEP 8: Stop
PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define N 5
#define BUFSIZE 1
#define PERMS 0666
int *buffer;
int nextp = 0, nextc = 0;
int mutex, full, empty; /* semaphore variables */
void producer()
{
int data;
if(nextp == N)
nextp = 0;
printf("Enter data for producer to produce : ");
scanf("%d",(buffer + nextp));
nextp++;
}
void consumer()
{
int g;
if(nextc == N)
nextc = 0;
g = *(buffer + nextc++);
printf("\nConsumer consumes data %d", g);
}
void sem_op(int id, int value)
{
struct sembufop;
int v;
op.sem_num = 0;
op.sem_op = value;
op.sem_flg = SEM_UNDO;
if((v = semop(id, &op, 1)) < 0)
printf("\nError executing semop instruction");
}
void sem_create(int semid, int initval)
{
int semval;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
} s;
s.val = initval;
if((semval = semctl(semid, 0, SETVAL, s)) < 0)
printf("\nError in executing semctl");
}
void sem_wait(int id)
{
int value = -1;
sem_op(id, value);
}
void sem_signal(int id)
{
int value = 1;
sem_op(id, value);
}
main()
{
int shmid, i;
pid_tpid;
if((shmid = shmget(1000, BUFSIZE, IPC_CREAT|PERMS)) < 0)
{
printf("\nUnable to create shared memory");
return;
}
if((buffer = (int*)shmat(shmid, (char*)0, 0)) == (int*)-1)
{
printf("\nShared memory allocation error\n");
exit(1);
}
if((mutex = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create mutex semaphore");
exit(1);
}
if((empty = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create empty semaphore");
exit(1);
}
if((full = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create full semaphore");
exit(1);
}
sem_create(mutex, 1);
sem_create(empty, N);
sem_create(full, 0);
if((pid = fork()) < 0)
{
printf("\nError in process creation");
exit(1);
}
else if(pid> 0)
{
for(i=0; i<N; i++)
{
sem_wait(empty);
sem_wait(mutex);
producer();
sem_signal(mutex);
sem_signal(full);
}
}
else if(pid == 0)
{
for(i=0; i<N; i++)
{
sem_wait(full);
sem_wait(mutex);
consumer();
sem_signal(mutex);
sem_signal(empty);
}
printf("\n");
}

OUTPUT:

RESULT:

INFERENCE:
EX.NO:8 DATE:
BANKERS ALGORITHM FOR DEADLOCK AVOIDANCE

AIM
To implement deadlock avoidance by using Banker’s Algorithm.

ALGORITHM
STEP 1: Start the program.

STEP 2: Get the values of resources and processes.

STEP 3: Get the avail value.

STEP 4: After allocation find the need value.

STEP 5: Check whether its possible to allocate.

STEP 6: If it is possible then the system is in safe state.

STEP 7: Else system is not in safety state.

STEP 8: If the new request comes then check that the system is in safety or not if we
allow the request.

STEP 9: Stop

PROGRAM
#include<stdio.h>
#include<stdio.h>
main()
{
int r[1][10], av[1][10];
int all[10][10], max[10][10], ne[10][10], w[10],safe[10];
int i=0, j=0, k=0, l=0, np=0, nr=0, count=0, cnt=0;
printf("enter the number of processes in a system");
scanf("%d", &np);
printf("enter the number of resources in a system");
scanf("%d",&nr);
for(i=1; i<=nr; i++)
{
printf("Enter no. of instances of resource R%d " ,i);
scanf("%d", &r[0][i]);
av[0][i] = r[0][i];
}
for(i=1; i<=np; i++)
for(j=1; j<=nr; j++)
all[i][j] = ne[i][j] = max[i][j] = w[i]=0;
printf("Enter the allocation matrix");
for(i=1; i<=np; i++)
{
for(j=1; j<=nr; j++)
{
scanf("%d", &all[i][j]);
av[0][j] = av[0][j] - all[i][j];
}
}
printf("Enter the maximum matrix");
for(i=1; i<=np; i++)
{
for(j=1; j<=nr; j++)
{
scanf("%d",&max[i][j]);
}
}
for(i=1; i<=np; i++)
{
for(j=1; j<=nr; j++)
{
ne[i][j] = max[i][j] - all[i][j];
}
}
for(i=1; i<=np; i++)
{
printf("pocessP%d", i);
for(j=1; j<=nr; j++)
{
printf("\n allocated %d\t",all[i][j]);
printf("maximum %d\t",max[i][j]);
printf("need %d\t",ne[i][j]);
}
printf("\n_________________________\n");
}
printf("\nAvailability ");
for(i=1; i<=nr; i++)
printf("R%d %d\t", i, av[0][i]);
printf("\n____________");
printf("\n safe sequence");
for(count=1; count<=np; count++)
{
for(i=1; i<=np; i++)
{
cnt = 0;
for(j=1; j<=nr; j++)
{
if(ne[i][j] <= av[0][j] && w[i]==0)
cnt++;
}
if(cnt == nr)
{
k++;
safe[k] = i;
for(l=1; l<=nr; l++)
av[0][l] = av[0][l] + all[i][l];
printf("\n P%d ",safe[k]);
printf("\t Availability ");
for(l=1; l<=nr; l++)
printf("R%d %d\t", l, av[0][l]);
w[i]=1;
}}}
}
OUTPUT:

RESULT:

INFERENCE:
EX.NO:9 DATE:
DEAD LOCK PREVENTION

AIM
To determine whether the process and their request for resources are in a deadlocked
state.

ALGORITHM
STEP 1: Mark each process that has a row in the Allocation matrix of all zeros.
STEP 2: Initialize a temporary vectorW to equal the Available vector.
STEP 3: Find an indexi such that processi is currently unmarked and the Ith row ofQ
is less than or equal to W . That is,Qik … Wk, for 1 … k … m . If no such row is found,
terminate the algorithm.
STEP 4: If such a row is found, mark processi and add the corresponding row of the
6:allocation
matrix to W . That is, setWk = Wk + Aik, for 1 … k … m . return to step 3:

PROGRAM
#include<stdio.h>
#include<stdlib.h>
int max[100][100];
int alloc[100][100];
int need[100][100];
int avail[100];
int n, r;
void input();
void show();
void cal();
main()
{
int i,j;
printf("Deadlock Detection Algo\n");
input();
show();
cal();
}
void input()
{
int i,j;
printf("Enter the no of Processes\t");
scanf("%d",&n);
printf("Enter the no of resource instances\t");
scanf("%d", &r);
printf("Enter the Max Matrix\n");
for(i=0; i<n; i++)
for(j=0; j<r; j++)
scanf("%d", &max[i][j]);
printf("Enter the Allocation Matrix\n");
for(i=0; i<n; i++)
for(j=0; j<r; j++)
scanf("%d", &alloc[i][j]);
printf("Enter the available Resources\n");
for(j=0;j<r;j++)
scanf("%d",&avail[j]);
}
void show()
{
int i, j;
printf("Process\t Allocation\t Max\t Available\t");
for(i=0; i<n; i++)
{
printf("\nP%d\t ", i+1);
for(j=0; j<r; j++)
{
printf("%d ", alloc[i][j]);
}
printf("\t");
for(j=0; j<r; j++)
{
printf("%d ", max[i][j]);
}
printf("\t");
if(i == 0)
{
for(j=0; j<r; j++)
printf("%d ", avail[j]);
}
}
}
void cal()
{
int finish[100], temp, need[100][100], flag=1, k, c1=0;
int dead[100];
int safe[100];
int i, j;
for(i=0; i<n; i++)
{
finish[i] = 0;
}
for(i=0; i<n; i++)
{
for(j=0; j<r; j++)
{
need[i][j]= max[i][j] - alloc[i][j];
}
}
while(flag)
{
flag=0;
for(i=0;i<n;i++)
{
int c=0;
for(j=0;j<r;j++)
{
if((finish[i]==0) && (need[i][j] <= avail[j]))
{
c++;
if(c == r)
{
for(k=0; k<r; k++)
{
avail[k] += alloc[i][j];
finish[i]=1;
flag=1;
}
if(finish[i] == 1)
{
i=n;
}
}
}
}
}
}
j = 0;
flag = 0;
for(i=0; i<n; i++)
{
if(finish[i] == 0)
{
dead[j] = i;
j++;
flag = 1;
}
}
if(flag == 1)
{
printf("\n\nSystem is in Deadlock and the Deadlock process are\n");
for(i=0;i<n;i++)
{
printf("P%d\t", dead[i]);
}
}
else
{
printf("\nNo Deadlock Occur");
}
}

OUTPUT:
RESULT:

INFERENCE:
EX.NO:10 DATE:
THREADING AND SYNCHRONIZATION
AIM
To demonstrate threading and synchronization using mutex.
Description
 Thread synchronization is defined as a mechanism which ensures that two or
more concurrent processes or threads do not simultaneously execute some
particular program segment known as critical section.
 Processes’ access to critical section is controlled by using synchronization
techniques.
 When one thread starts executing the critical section (serialized segment of
the program) the other thread should wait until the first thread finishes.
 If proper synchronization techniques are not applied, it may cause a race
condition where the values of variables may be unpredictable
 Mutex is a lock that we set before using a shared resource and release after
using it.
 When the lock is set, no other thread can access the locked region of code.
So this ensures a synchronized access of shared resources in the code

ALGORITHM
STEP 1: Create two threads
STEP 2: Let the threads share a common resource, say counter
STEP 3: Even if thread2 si scheduled to start while thread was not done, access to
shared resource isnot done as it is locked by mutex
STEP 4: Once thread1 completes, thread2 starts execution
STEP 5: Stop

PROGRAM
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_ttid[2];
int counter;
pthread_mutex_tlock;
void* trythis(void *arg)
{
pthread_mutex_lock(&lock);
unsigned long i = 0;
counter += 1;
printf("\n Job %d has started\n", counter);
for(i=0; i<(0xFFFFFFFF);i++);
printf("\n Job %d has finished\n", counter);
pthread_mutex_unlock(&lock);
return NULL;
}
main()
{
int i = 0;
int error;
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init has failed\n");
return 1;
}
while(i< 2)
{
err = pthread_create(&(tid[i]), NULL, &trythis, NULL);
if (error != 0)
printf("\nThread can't be created :[%s]",strerror(error));
i++;
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_mutex_destroy(&lock);
return 0;
}

$ ./a.out
Job 1 started
OUTPUT:

RESULT:

INFERENCE:
EX.NO:11 DATE:
FIRST FIT ALLOCATION
AIM
To allocate memory requirements for processes using first fit allocation.
Memory Management
 The first-fit, best-fit, or worst-fit strategy is used to select a free hole from the
set of available holes.

First fit
 Allocate the first hole that is big enough.
 Searching starts from the beginning of set of holes.

ALGORITHM
STEP 1: Declare structures hole and process to hold information about set of holes and
processes
respectively.
STEP 2: Get number of holes, say nh.
STEP 3: Get the size of each hole
STEP 4: Get number of processes, say np.
STEP 5: Get the memory requirements for each process.
STEP 6: Allocate processes to holes, by examining each hole as follows:
a. If hole size > process size then
i. Mark process as allocated to that hole.
ii. Decrement hole size by process size.
b. Otherwise check the next from the set of hole
STEP 7: Print the list of process and their allocated holes or unallocated status.
STEP 8: Print the list of holes, their actual and current availability.
STEP 9: Stop

PROGRAM
#include <stdio.h>
struct process
{
int size;
int flag;
int holeid;
} p[10];
struct hole
{
int size;
int actual;
} h[10];
main()
{
int i, np, nh, j;
printf("Enter the number of Holes : ");
scanf("%d", &nh);
for(i=0; i<nh; i++)
{
printf("Enter size for hole H%d : ",i);
scanf("%d", &h[i].size);
h[i].actual = h[i].size;
}
printf("\nEnter number of process : " );
scanf("%d",&np);
for(i=0;i<np;i++)
{
printf("enter the size of process P%d : ",i);
scanf("%d", &p[i].size);
p[i].flag = 0;
}
for(i=0; i<np; i++)
{
for(j=0; j<nh; j++)
{
if(p[i].flag != 1)
{
if(p[i].size<= h[j].size)
{
p[i].flag = 1;
p[i].holeid = j;
h[j].size -= p[i].size;
}
}
}
}
printf("\n\tFirst fit\n");
printf("\nProcess\tPSize\tHole");
for(i=0; i<np; i++)
{
if(p[i].flag != 1)
printf("\nP%d\t%d\tNot allocated", i, p[i].size);
else
printf("\nP%d\t%d\tH%d", i, p[i].size, p[i].holeid);
}
printf("\n\nHole\tActual\tAvailable");
for(i=0; i<nh ;i++)
printf("\nH%d\t%d\t%d", i, h[i].actual, h[i].size);
printf("\n");
}
OUTPUT:

BEST FIT ALLOCATION


Best fit
 Allocate the smallest hole that is big enough.
 The list of free holes is kept sorted according to size in ascending order.
 This strategy produces smallest leftover holes

ALGORITHM
STEP 1: Declare structures hole and process to hold information about set of holes
and processes
respectively.
STEP 2: Get number of holes, say nh.
STEP 3: Get the size of each hole
STEP 4: Get number of processes, say np.
STEP 5: Get the memory requirements for each process.
STEP 6: Allocate processes to holes, by examining each hole as follows:
a. Sort the holes according to their sizes in ascending order
b. If hole size > process size then
i. Mark process as allocated to that hole.
ii. Decrement hole size by process size.
c. Otherwise check the next from the set of sorted hole
STEP 7: Print the list of process and their allocated holes or unallocated status.
STEP 8: Print the list of holes, their actual and current availability.
STEP 9: Stop
PROGRAM
#include <stdio.h>
struct process
{
int size;
int flag;
int holeid;
} p[10];
struct hole
{
int hid;
int size;
int actual;
} h[10];
main()
{
int i, np, nh, j;
void bsort(struct hole[], int);
printf("Enter the number of Holes : ");
scanf("%d", &nh);
for(i=0; i<nh; i++)
{
printf("Enter size for hole H%d : ",i);
scanf("%d", &h[i].size);
h[i].actual = h[i].size;
h[i].hid = i;
}
printf("\nEnter number of process : " );
scanf("%d",&np);
for(i=0;i<np;i++)
{
printf("enter the size of process P%d : ",i);
scanf("%d", &p[i].size);
p[i].flag = 0;
}
for(i=0; i<np; i++)
{
bsort(h, nh);
for(j=0; j<nh; j++)
{
if(p[i].flag != 1)
{
if(p[i].size<= h[j].size)
{
p[i].flag = 1;
p[i].holeid = h[j].hid;
h[j].size -= p[i].size;
}
}
}
}
printf("\n\tBest fit\n");
printf("\nProcess\tPSize\tHole");
for(i=0; i<np; i++)
{
if(p[i].flag != 1)
printf("\nP%d\t%d\tNot allocated", i, p[i].size);
else
printf("\nP%d\t%d\tH%d", i, p[i].size, p[i].holeid);
}
printf("\n\nHole\tActual\tAvailable");
for(i=0; i<nh ;i++)
printf("\nH%d\t%d\t%d", h[i].hid, h[i].actual,
h[i].size);
printf("\n");
}
void bsort(struct hole bh[], int n)
{
struct hole temp;
int i,j;
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if(bh[i].size>bh[j].size)
{
temp = bh[i];
bh[i] = bh[j];
bh[j] = temp;
}
}
}
}
OUTPUT:

RESULT:

INFERENCE:
EX.NO:12 DATE:
PAGING TECHNIQUE
AIM
To determine physical address of a given page using page table..

ALGORITHM
STEP 1: Get process size
STEP 2:Compte no. of pages available and display it
STEP 3: Get relative address
STEP 4: Determine the corresponding page
STEP 5: Display page table
STEP 6: Display the physical address.

PROGRAM
#include <stdio.h>
#include <math.h>
main()
{
int size, m, n, pgno, pagetable[3]={5,6,7}, i, j, frameno;
double m1;
int ra=0, ofs;
printf("Enter process size (in KB of max 12KB):");
scanf("%d", &size);
m1 = size / 4;
n = ceil(m1);
printf("Total No. of pages: %d", n);
printf("\nEnter relative address (in hexa) \n");
scanf("%d", &ra);
pgno = ra / 1000;
ofs = ra % 1000;
printf("page no=%d\n", pgno);
printf("page table");
for(i=0;i<n;i++)
printf("\n %d [%d]", i, pagetable[i]);
frameno = pagetable[pgno];
printf("\nPhysical address: %d%d", frameno, ofs);
}

OUTPUT:

RESULT:

INFERENCE:
EX.NO:13 DATE:
FIFO PAGE REPLACEMNET
AIM
To implement demand paging for a reference string using FIFO method.
FIFO
 Page replacement is based on when the page was brought into memory.
 When a page should be replaced, the oldest one is chosen.
 Generally, implemented using a FIFO queue.
 Simple to implement, but not efficient.
 Results in more page faults.
 The page-fault may increase, even if frame size is increased (Belady's
anomaly)

ALGORITHM
STEP 1: Get length of the reference string, say l.
STEP 2: Get reference string and store it in an array, say rs.
STEP 3: Get number of frames, say nf.
STEP 4:Initalize frame array upto length nf to -1:
STEP 5: Initialize position of the oldest page, say j to 0.
STEP 6: Initialize no. of page faults, say count to 0.
STEP 7: For each page in reference string in the given order, examine:
a. Check whether page exist in the frame array
b. If it does not exist then
i. Replace page in position j.
ii. Compute page replacement position as (j+1) modulus nf.
iii. Increment count by 1:
iv. Display pages in frame array.
STEP 8: Print count.
STEP 9: Stop.

PROGRAM
#include <stdio.h>
main()
{
int i,j,l,rs[50],frame[10],nf,k,avail,count=0;
printf("Enter length of ref. string : ");
scanf("%d", &l);
printf("Enter reference string :\n");
for(i=1; i<=l; i++)
scanf("%d", &rs[i]);
printf("Enter number of frames : ");
scanf("%d", &nf);
for(i=0; i<nf; i++)
frame[i] = -1;
j = 0;
printf("\nRef. str Page frames");
for(i=1; i<=l; i++)
{
printf("\n%4d\t", rs[i]);
avail = 0;
for(k=0; k<nf; k++)
if(frame[k] == rs[i])
avail = 1;
if(avail == 0)
{
frame[j] = rs[i];
j = (j+1) % nf;
count++;
for(k=0; k<nf; k++)
printf("%4d", frame[k]);
}
}
printf("\n\nTotal no. of page faults : %d\n",count);
}

OUTPUT:
LRU PAGE REPLACEMENT
LRU
 Pages used in the recent past are used as an approximation of future usage.
 The page that has not been used for a longer period of time is replaced.
 LRU is efficient but not optimal.
 Implementation of LRU requires hardware support, such as counters/stack

ALGORITHM
STEP 1: Get length of the reference string, say len.
STEP 2: Get reference string and store it in an array, say rs.
STEP 3: Get number of frames, say nf.
STEP 4: Create access array to store counter that indicates a measure of recent usage.
STEP 5: Create a function arrmin that returns position of minimum of the given
array.
STEP 6:Initalize frame array upto length nf to -1:
STEP 7: Initialize position of the page replacement, say j to 0.
STEP 8: Initialize freq to 0 to track page frequency
STEP 9: Initialize no. of page faults, say count to 0.
STEP 10: For each page in reference string in the given order, examine:
a. Check whether page exist in the frame array.
b. If page exist in memory then
i. Store incremented freq for that page position in access array.
c. If page does not exist in memory then
i. Check for any empty frames.
ii. If there is an empty frame,
 Assign that frame to the page
 Store incremented freq for that page position in access array.
 Increment count.
iii. If there is no free frame then
 Determine page to be replaced using arrmin function.
 Store incremented freq for that page position in access array.
 Increment count.
iv. Display pages in frame array.
STEP 11: Print count.
STEP 12: Stop
PROGRAM
#include <stdio.h>
int arrmin(int[], int);
main()
{
int i,j,len,rs[50],frame[10],nf,k,avail,count=0;
int access[10], freq=0, dm;
printf("Length of Reference string : ");
scanf("%d", &len);
printf("Enter reference string :\n");
for(i=1; i<=len; i++)
scanf("%d", &rs[i]);
printf("Enter no. of frames : ");
scanf("%d", &nf);
for(i=0; i<nf; i++)
frame[i] = -1;
j = 0;
printf("\nRef. str Page frames");
for(i=1; i<=len; i++)
{
printf("\n%4d\t", rs[i]);
avail = 0;
for(k=0; k<nf; k++)
{
if(frame[k] == rs[i])
{
avail = 1;
access[k] = ++freq;
break;
}
}
if(avail == 0)
{
dm = 0;
for(k=0; k<nf; k++)
{
if(frame[k] == -1)
dm = 1;
break;
}
if(dm == 1)
{
frame[k] = rs[i];
access[k] = ++freq;
count++;
}
else
{
j = arrmin(access, nf);
frame[j] = rs[i];
access[j] = ++freq;
count++;
}
for(k=0; k<nf; k++)
printf("%4d", frame[k]);
}
}
printf("\n\nTotal no. of page faults : %d\n", count);
}
int arrmin(int a[], int n)
{
int i, min = a[0];
for(i=1; i<n; i++)
if (min > a[i])
min = a[i];
for(i=0; i<n; i++)
if (min == a[i])
return i;
}
OUTPUT:

RESULT:

INFERENCE:
EX.NO:14 DATE:
SINGLE LEVEL DIRECTORY
AIM
To organize files in a single level directory structure, I,e., without sub-directories

ALGORITHM
STEP 1: Get name of directory for the user to store all the files
STEP 2: Display menu
STEP 3: Accept choice
STEP 4: If choice =1 then
Accept filename without any collission
Store it in the directory
STEP 5: If choice =2 then
Accept filename
Remove filename from the directory array
STEP 6: If choice =3 then
Accept filename
Check for existence of file in the directory array
STEP 7: If choice =4 then List all files in the directory array
STEP 8: If choice =5 then
STEP 9:Stop

PROGRAM
#include <stdio.h>
#include <stdlib.h>
struct
{
char dname[10];
char fname[25][10];
int fcnt;
}dir;
main()
{
int i, ch;
char f[30];
dir.fcnt = 0;
printf("\nEnter name of directory -- ");
scanf("%s", dir.dname);
while(1)
{
printf("\n\n 1: Create File\t2: Delete File\t3: Search File \n4: Display Files\t5:
Exit\nEnter your choice--");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\n Enter the name of the file -- ");
scanf("%s", dir.fname[dir.fcnt]);
dir.fcnt++;
break;
case 2:
printf("\n Enter the name of the file -- ");
scanf("%s", f);
for(i=0; i<dir.fcnt; i++)
{
if(strcmp(f, dir.fname[i]) == 0)
{
printf("File %s is deleted ",f);
strcpy(dir.fname[i], dir.fname[dir.fcnt-1]);
break;
}
}
if(i == dir.fcnt)
printf("File %s not found", f);
else
dir.fcnt--;
break;
case 3:
printf("\n Enter the name of the file -- ");
scanf("%s", f);
for(i=0; i<dir.fcnt; i++)
{
if(strcmp(f, dir.fname[i]) == 0)
{
printf("File %s is found ", f);
break;
}
}
if(i == dir.fcnt)
printf("File %s not found", f);
break;
case 4:
if(dir.fcnt == 0)
printf("\n Directory Empty");
else
{
printf("\n The Files are -- ");
for(i=0; i<dir.fcnt; i++)
printf("\t%s", dir.fname[i]);
}
break;
default:
exit(0);
}
}
getch();
}
4: Display Files 5: Exit
Enter your choice -- 1
Enter the name of the file -- sjf
1: Create File 2: Delete File 3: Search File
4: Display Files 5: Exit
Enter your choice -- 1
Enter the name of the file -- lru
OUTPUT:

TWO LEVEL DIRECTORY


ALGORITHM
STEP 1: Display menu
STEP 2: Accept choice
STEP 3: If choice =1 then
Accept directory name
Create an entry for that directory
STEP 4: If choice =2 then
Get directory name
If directory exist then accept filename without collision else report error
STEP 5: If choice =3 then
Get directory name
If directory exist then Get filename
If file exist in that directory then delete entry else report error
STEP 6: If choice =4 then
Get directory name
If directory exist then Get filename
If file exist in that directory then Display filename else report error
STEP 7: If choice =5 then Display files directory-wise
STEP 8: If choice =6 then Stop

PROGRAM
#include <stdio.h>
#include <stdlib.h>
struct
{
char dname[10], fname[10][10];
int fcnt;
}dir[10];
main()
{
int i, ch, dcnt, k;
char f[30], d[30];
dcnt=0;
while(1)
{
printf("\n\n 1: Create Directory\t 2: Create File\t 3:Delete File");
printf("\n 4: Search File \t \t 5: Display \t 6: Exit \nEnter your choice -- ");
scanf("%d", &ch);
switch(ch)
{
case 1:
printf("\n Enter name of directory -- ");
scanf("%s", dir[dcnt].dname);
dir[dcnt].fcnt = 0;
dcnt++;
printf("Directory created");
break;
case 2:
printf("\n Enter name of the directory -- ");
scanf("%s", d);
for(i=0; i<dcnt; i++)
if(strcmp(d,dir[i].dname) == 0)
{
printf("Enter name of the file -- ");
scanf("%s", dir[i].fname[dir[i].fcnt]);
dir[i].fcnt++;
printf("File created");
break;
}
if(i == dcnt)
printf("Directory %s not found",d);
break;
case 3:
printf("\nEnter name of the directory -- ");
scanf("%s", d);
for(i=0; i<dcnt; i++)
{
if(strcmp(d,dir[i].dname) == 0)
{
printf("Enter name of the file -- ");
scanf("%s", f);
for(k=0; k<dir[i].fcnt; k++)
{
if(strcmp(f, dir[i].fname[k]) == 0)
{
printf("File %s is deleted ", f);
dir[i].fcnt--;
strcpy(dir[i].fname[k],
dir[i].fname[dir[i].fcnt]);
gotojmp;
}
}
printf("File %s not found",f);
gotojmp;
}
}
printf("Directory %s not found",d);
jmp : break;
case 4:
printf("\nEnter name of the directory -- ");
scanf("%s", d);
for(i=0; i<dcnt; i++)
{
if(strcmp(d,dir[i].dname) == 0)
{
printf("Enter the name of the file -- ");
scanf("%s", f);
for(k=0; k<dir[i].fcnt; k++)
{
if(strcmp(f, dir[i].fname[k]) == 0)
{
printf("File %s is found ", f);
gotojmp1;
}
}
printf("File %s not found", f);
gotojmp1;
}
}
printf("Directory %s not found", d);
jmp1: break;
case 5:
if(dcnt == 0)
printf("\nNo Directory's ");
else
{
printf("\nDirectory\tFiles");
for(i=0;i<dcnt;i++)
{
printf("\n%s\t\t",dir[i].dname);
for(k=0;k<dir[i].fcnt;k++)
printf("\t%s",dir[i].fname[k]);
}
}
break;
default:
exit(0);
}
}
getch();
}

OUTPUT:

RESULT:

INFERENCE:
EX.No:15 DATE:
CONTIGUOUS ALLOCATION
AIM
To implement file allocation on free disk space in a contiguous manner.
File Allocation
 The three methods of allocating disk space are:
1: Contiguous allocation
2: Linked allocation
3: Indexed allocation
Contiguous
 Each file occupies a set of contiguous block on the disk.
 The number of disk seeks required is minimal.
 The directory contains address of starting block and number of contiguous block
(length) occupied.
 Supports both sequential and direct access.
 First / best fit is commonly used for selecting a hole.

ALGORITHM
STEP 1: Assume no. of blocks in the disk as 20 and all are free.
STEP 2: Display the status of disk blocks before allocation.
STEP 3: For each file to be allocated:
a. Get the filename, start address and file length
b. If start + length > 20, then goto step 2:
c. Check to see whether any block in the range (start, start + length-1) is allocated. If
so, then go to step 2:
d. Allocate blocks to the file contiguously from start block to start + length – 1:
STEP 4: Display directory entries.
STEP 5: Display status of disk blocks after allocation
STEP 6: Stop
PROGRAM
#include <stdio.h>
#include <string.h>
int num=0, length[10], start[10];
char fid[20][4], a[20][4];
void directory()
{
int i;
printf("\nFile Start Length\n");
for(i=0; i<num; i++)
printf("%-4s %3d %6d\n",fid[i],start[i],length[i]);
}
void display()
{
int i;
for(i=0; i<20; i++)
printf("%4d",i);
printf("\n");
for(i=0; i<20; i++)
printf("%4s", a[i]);
}
main()
{
int i,n,k,temp,st,nb,ch,flag;
char id[4];
for(i=0; i<20; i++)
strcpy(a[i], "");
printf("Disk space before allocation:\n");
display();
do
{
printf("\nEnter File name (max 3 char) : ");
scanf("%s", id);
printf("Enter start block : ");
scanf("%d", &st);
printf("Enter no. of blocks : ");
scanf("%d", &nb);
strcpy(fid[num], id);
length[num] = nb;
flag = 0;

if((st+nb) > 20)


{
printf("Requirement exceeds range\n");
continue;
}
for(i=st; i<(st+nb); i++)
if(strcmp(a[i], "") != 0)
flag = 1;
if(flag == 1)
{
printf("Contiguous allocation not possible.\n");
continue;
}
start[num] = st;
for(i=st; i<(st+nb); i++)
strcpy(a[i], id);;
printf("Allocation done\n");
num++;
printf("\nAny more allocation (1: yes / 2: no)? : ");
scanf("%d", &ch);
} while (ch == 1);
printf("\n\t\t\tContiguous Allocation\n");
printf("Directory:");
directory();
printf("\nDisk space after allocation:\n");
display();
}

OUTPUT:
LINKED FILE ALLOCATION
Linked
 Each file is a linked list of disk blocks.
 The directory contains a pointer to first and last blocks of the file.
 The first block contains a pointer to the second one, second to third and so
on.
 File size need not be known in advance, as in contiguous allocation.
 No external fragmentation.
 Supports sequential access only.

Indexed
 In indexed allocation, all pointers are put in a single block known as index
block.
 The directory contains address of the index block.
 The ith entry in the index block points to ith block of the file.
 Indexed allocation supports direct access.
 It suffers from pointer overhead, i.e wastage of space in storing pointers

ALGORITHM
STEP 1: Get no. of files
STEP 2: Accept filenames and no. of blocks fo each file
STEP 3:Obtrain start block for each file
STEP 4: Obtain other blocks for each file
STEP 5: Check block availability before allocation
STEP 6: If block is unavailable then report error
STEP 7: Accept file name
STEP 8: Display linked file allocation blocks for that file
STEP 9: Stop

PROGRAM
#include <stdio.h>
#include <string.h>
main()
{
static int b[20], i, j, blocks[20][20];
char F[20][20], S[20], ch;
int sb[20], eb[20], x, n;
printf("\n Enter no. of Files ::");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\n Enter file %d name ::", i+1);
scanf("%s", &F[i]);
printf("\n Enter No. of blocks::", i+1);
scanf("%d",&b[i]);
}

for(i=0;i<n;i++)
{
printf("\n Enter Starting block of file%d::",i+1);
scanf("%d", &sb[i]);
printf("\nEnter blocks for file%d::\n", i+1);
for(j=0; j<b[i]-1;)
{
printf("\n Enter the %dblock ::", j+2);
scanf("%d", &x);
if(b[i] != 0)
{
blocks[i][j] = x;
j++;
}
else
printf("\n Invalid block::");
}
}
printf("\nEnter the Filename :");
scanf("%s", &S);
for(i=0; i<n; i++)
{
if(strcmp(F[i],S) == 0)
{
printf("\nFname\tBsize\tStart\tBlocks\n");
printf("\n--------------------------------------\n");
printf("\n%s\t%d\t%d\t", F[i], b[i], sb[i]);
printf("%d->",sb[i]);
for(j=0; j<b[i]; j++)
{
if(b[i] != 0)
printf("%d->", blocks[i][j]);
}
}
}
printf("\n-------------------------------------------\n");
}

OUTPUT:

RESULT:

INFERENCE:
CASE STUDY- ANDROID OS

INTRODUCTION
Android is a mobile operating system based on a modified version of the Linux
kernel and other open-source software, designed primarily for touchscreen mobile devices
such as smartphones and tablets. It is an operating system for low powered devices that run
on battery and are full of hardware like Global Positioning System (GPS) receivers,
cameras, light and orientation sensors, Wi-Fi and LTE (4G telephony) connectivity and a
touch screen. Like all operating systems, Android enables applications to make use of the
hardware features through abstraction and provide a defined environment for applications.

HISTORY
The platform was created by Android Inc. which was bought by Google and released as the
Android Open-Source Project (AOSP) in 2007: Since then, Android has seen numerous
updates which have incrementally improved the operating system, adding new features and
fixing bugs in previous releases. Each major release is named in alphabetical order after a
dessert or sugary treat, with the first few Android versions being called "Cupcake", "Donut",
"Eclair", and "Froyo", in that order. During its announcement of Android KitKat in 2013,
Google explained that "Since these devices make our lives so sweet, each Android version is
named after a dessert". This changed after android pie.

ANDROID ARCHITECTURE:
 THE LINUX KERNAL:
The foundation of the Android platform is the Linux kernel. For example, the
Android Runtime (ART) relies on the Linux kernel for underlying functionalities
such as threading and low-level memory management. Using a Linux kernel allows
Android to take advantage of key security features and allows device manufacturers
to develop hardware drivers for a well-known kernel.
 HARDWARE ABSTRACTION LAYER (HAL):
The hardware abstraction layer (HAL) provides standard interfaces that
expose device hardware capabilities to the higher-level Java API framework. The
HAL consists of multiple library modules, each of which implements an interface for
a specific type of hardware component, such as the camera or Bluetooth module.
When a framework API makes a call to access device hardware, the Android system
loads the library module for that hardware component.
 ANDROID RUNTIME
Each app runs in its own process and with its own instance of the Android
Runtime (ART). ART is written to run multiple virtual machines on low-memory
devices by executing DEX files, a bytecode format designed especially for Android
that's optimized for minimal memory footprint. Build tools, such as d8, compile Java
sources into DEX bytecode, which can run on the Android platform.

 NATIVE C/C++ LIBRARIES


Many core Android system components and services, such as ART and HAL,
are built from native code that require native libraries written in C and C++. The
Android platform provides Java framework APIs to expose the functionality of some
of these native libraries to apps. For example, you can access OpenGL ES through
the Android framework’s Java OpenGL API to add support for drawing and
manipulating 2D and 3D graphics in your app.
 JAVA API FRAMEWORK
The entire feature-set of the Android OS is available to you through APIs
written in the Java language. These APIs form the building blocks you need to create
Android apps by simplifying the reuse of core, modular system components and
services, which include the following:
o A rich and extensible View System you can use to build an app’s UI,
including lists, grids, text boxes, buttons, and even an embeddable web
browser.
o A Resource Manager, providing access to non-code resources such as
localized strings, graphics, and layout files.
o A Notification Manager that enables all apps to display custom alerts in the
status bar
o An Activity Manager that manages the lifecycle of apps and provides a
common navigation back stack.
o Content Providers that enable apps to access data from other apps, such as the
Contacts app, or to share their own data
 SYSTEM APPS
Android comes with a set of core apps for email, SMS messaging, calendars,
internet browsing, contacts, and more. Apps included with the platform have no
special status among the apps the user chooses to install. So, a third-party app can
become the user's default web browser, SMS messenger, or even the default
keyboard (some exceptions apply, such as the system's Settings app).

CPU SCHEDULING:
The Android operating system uses O (1) scheduling algorithm as it is based on
Linux Kernel 2:6: Therefore, the scheduler is named as Completely Fair Scheduler as the
processes can schedule within a constant amount of time, regardless of how many processes
are running on the operating system.
The process "nice" level impacts the normal "fair" scheduling policy of Linux;
threads that have a higher niceness will be run less often than threads with a lower niceness
hus if you set a thread's priority to Process.THREAD_PRIORITY_BACKGROUND or
greater, you will also be putting the thread into the background cgroup. Set it to
Process.THREAD_PRIORITY_DEFAULT and it will be in the default cgroup.. In the
situation where you have one thread at a "default" priority (as defined in
Process.THREAD_PRIORITY_DEFAULT) will get to run significantly more often than
those at a background priority (or Process.THREAD_PRIORITY_BACKGROUND).
In theory this can make sure that the foreground/UI threads aren't impacted
significantly by background work... however, in practice, it isn't sufficient.
To address this, Android also uses Linux cgroups in a simple way to create stricter
foreground vs. background scheduling. The foreground/default cgroup allows thread
scheduling as normal. The background cgroup however applies a limit of only some small
percent of the total CPU time being available to all threads in that cgroup. Android
implicitly moves threads between the default and background cgroups when you use its
public APIs to set the thread priority.
Because of this, by following the normal convention of putting your background
worker threads into the background priority you can ensure that they do not disrupt your
foreground UI thread.
In addition, Android will also move all threads in a process to the background cgroup
for processes that it knows are not critical to the user. Any background process or service
process has its threads put into the background cgroup, regardless of whether individual
threads have requested a foreground scheduling priority.

STORAGE MANAGEMENT:
There are two things that the OS is supposed to do in managing the Internal storage.
First lookout for filled space and others give app access to read/write in internal
storage. In android 10 and above apps can be given only access to media elements of the
device. Most android use e-MMC based storage. They provide up to 300MBps read and
write speed. File system in android is that of a Linux having a root directory, they can be
seen in the image on the right. There are various partitions each having its features. Only
internal storage or memory cards are accessible to the user, rest all are managed by OS
itself.
Storage Manager is the interface to the system's storage service. The storage manager
handles storage-related items such as Opaque Binary Blobs (OBBs).
OBBs contain a filesystem that can be encrypted on disk and mounted on-demand
from an application. OBBs are a good way of providing large amounts of binary assets
without packaging them into APKs as they may be multiple gigabytes in size. However, due
to their size, they're most likely stored in a shared storage pool accessible from all programs.
The system does not guarantee the security of the OBB file itself: if any program modifies
the OBB, there is no guarantee that a read from that OBB will produce the expected output.

BATTERY OPTIMIZATION
Battery life is the single most important aspect of the mobile user experience. A
device without power offers no functionality at all. For this reason, it is critically important
that apps be as respectful of battery life as possible.
There are three important things to keep in mind in keeping your app power-thrifty:
1) Make your apps Lazy First.
2) Take advantage of platform features that can help manage your app's battery
consumption.
3) Use tools that can help you identify battery-draining culprits.

 LAZY FIRST
Making your app Lazy First means looking for ways to reduce and optimize
operations that are particularly battery-intensive. The core questions underpinning
Lazy First design are:
1) Reduce: Are there redundant operations your app can cut out?
2) Defer: Does an app need to perform an action right away?
3) Coalesce: Can work be batched, instead of putting the device into an
active state many times?

 PLATFORM FEATURES
Broadly speaking, the Android platform provides two categories of help for
you to optimize your app's battery use. First, it provides several APIs that you can
implement in your app.
There are also internal mechanisms in the platform to help conserve battery
life. While they are not APIs that you implement programmatically, you should still
be aware of them so that your app can leverage them successfully.
Additionally, Android 9 (API level 28) makes a number of improvements to
battery saver mode. Device manufacturers determine the precise restrictions
imposed. As an example, on AOSP builds, the system applies the following
restrictions:
1) The system puts apps in app standby mode more aggressively, instead of
waiting for the app to be idle.
2) Background execution limits apply to all apps, regardless of their target
API level.
3) Location services may be disabled when the screen is off.
4) Background apps do not have network access.
As always, it's a good idea to test your app while the battery saver is active. You can
turn on the battery saver manually through the device's Settings > Battery Saver
screen.

 TOOLING:
You can get even more benefit out of these features by using the tools available for
the platform to discover the parts of your app that consume the most power. Finding
what to target is a big step toward successful optimization.
There are tools for Android, including Profile GPU Rendering and Battery Historian
to help you identify areas that you can optimize for better battery life. Take
advantage of these tools to target areas where you can apply the principles of Lazy
First.
CASE STUDY – IOS

INTRODUCTION
iPhone operating system(iOS) is a mobile operating system developed by Apple Inc.
used for apple handheld devices. It is used in devices like- iPhone, iPad and iPod. It is the
second most widely used mobile operating system. It supports features like direct
manipulation and can respond to various types of user gestures. It is proprietary and closed
source and derived from macOS. Software development kit (SDK) is provided to create
applications. It includes interfaces for developing, running and testing applications. Apps
can be written using system frameworks and Objective-C programming language.
Initial three versions were introduced with the name iPhone OS. From fourth
version, they renamed it to iOS. With each new version, new features and apps were added.
iOS 13 is latest version which was released in 2019: Its major feature is dark mode and new
Map application with street view capability. It also enhanced its previous apps and features
like-Siri, Heath map and others. iOS 14 is released in 2020.

FEATURES OF IOS
iOS is the operating system for iPhone, iPad and other Apple mobile devices. Based
on Mac OS, the operating system which runs Apple’s line of Mac desktop and laptop
computers, Apple iOS is designed for easy, seamless networking between Apple products.
iOS support extremely good features and some of the common features are:
 Multitasking– it allows is released be executed concurrently. This feature allows
various applications toruninbackgroundlike notifications, VoIP, audio, Bluetooth
access, app updates and may more.
 SpringBoard – It is used for managing home screen.
 Gesture recognition
 Wifi, Bluetooth and support for VPN
 Access to Apple App store
 Safari browser
 Front and read camera with videos capturing facility
 Siri – it is an intelligent personal assistant feature which can take voice queries and
can take and recommendations, used for setting reminders etc.
 Game center – it is multiplayer gaming network available online.
 Compatible with iCloud – iCloud is cloud service provided by Apple.
 Push email service – Apple’s email server allows mails to be delivered as they arrive.
 Accelerometer, gyroscope, and magnetometer – these are sensor interfaces used to
listen various events.
 Apple pay – it is payment technology which can store credit card details to pay for
services.
 Services like Maps, contacts, web pages, messages, location
 Various security features – face ID, pass code, 2 factor authentication.
 Home Pod – it can identify family members by voice and can handoff calls, music
etc on other devices.
 HomeKit – it is home automation controlling system.
 CarPlay – this allows interacting with iOS during drive. Also allows access tom
phone apps
EVOLUTION OF OS
iOS was first introduced with iPhone in Jan 2007 and released in June 2007: At first
introduction Steve Jobs claimed it to be running OS X and running desktop class application
but during release introduced it with the name “iPhone OS”. Initially, there was no support
for third party applications. In March 2008, Apple announced software development kit for
iPhone. In July 2008, iOS app store opened with 500 applications which increased to 3000
in Sept 2008 and after successive growth through the years increased to 2:2 million in 2017:
It is also estimated to reach 5 million by 2020. iOS has seen a lot of changes since its
inception. Following are the important milestones in iOS:
iOS was first introduced with iPhone in Jan 2007 and released in June 2007:
 Apple’s iOS first SDK was released on March 6, 2008:
 The initial release was named iPhone OS which was later changed to iOS on June 7,
2010:
 iPhone OS 1 was released on March 6, 2008, and is the first version of the popular
operating system. The support for iPhone OS 1 ended after two years, i.e., 2010:
 iPhone OS 2, as the name suggest, is the 2nd big release for the iOS. The release was
done in conjunction with iPhone 3G, and anyone with the previous version can easily
upgrade to the latest version. Also, this version introduced the App store, which
becomes the hub for installing new apps. New SDK was also released for developers
with support ending in 2011:
 The third big release was Apple iOS 3: It came into existence in June 2009 with
support ending in late 2012: New features such as copy, paste, etc. are added to the
OS.
 iOS 5 was released on June 6, 2001: It brought support for iPad Touch (3rd
generation) and iPad (1st generation).
 iOS 6 went live on September 19, 2012, for the 4thgenerationApple devices.
 iOS 7 was released for public on September 18, 2013: It supported two new phones
by Apple, the Apple iPhone 5S and iPhone 5C.
 Just like the old release, iOS 8 released for public on September 9, 2014, with
support for their best phone devices, the iPhone 6 and iPhone 6 Plus. They dropped
support for older devices.
 iOS 9 was made public on September 16, 2015: Apple changed how they support
legacy hardware and iOS 9 became the first Apple OS that supported 22 devices.
 iOS 10 was announced on June 13, 2016 at WWDC (Worldwide Developers
Conference event and was released to public in September, 2016 along with iPhone 7
and iPhone 7 plus.
 iOS 11 was made public on September, 2017 along with iPhone 8 and iPhone 8 Plus.
It has dropped 32-bit applications making iOS 11 as a 64-bit OS that only runs 64-
bit apps.
 iOS 12 was made public on September 2018 along with iPhone XS, iPhone XS Max,
iPhone XR.
 Apple announced iOS 13 and made public on September, 2019: The principal
features include Dark Mode and Emoji support. The NFC (Near Field
Communication) framework supports reading several types of contactless smartcards
and tags.
 Apple released iOS 14 and iPadOS 14 on 9th July 2020. All devices that support iOS
13 also support iOS 14: Some new features include widgets that be now be placed
directly on the home-screen, along with theApp library which automatically
categorizes apps into one page, Picture in Picture, Car- key technology to unlock and
start a car with NFC. It also allows the user to have incoming calls shown in banners
rather than taking up the whole screen.

ARCHITECTURE OF IOS
iOS architecture is written in Objective-C language and comprised of four layers
(layered architecture). It consists of a stack of four layers – Core OS, Core services, media
layer, and Cocoa Touch as shown in Figure 1:

Apps installed on system communicate with the iOS which in turn communicates
with the hardware. Bottom level layers in the iOS stack are responsible for basic services
while the upper layers are responsible for providing interface and graphics designing.
Apple provides system interfaces called Frameworks which is a package that stores 314
dynamic shared libraries. It contains various resources like – header files, supported apps,
images. Each layer of iOS contains different set of frameworks that can be used to
developers to design apps.

PROCESS AND THREADS MANAGEMENT


Everyprocessinanapplicationis created using one or more threads. Thread represents
single path of execution. Execution of a process starts with a single thread and can later
spawn multiple threads, where each thread performs a specific task.
All threads of a single process have same access rights and also shares same address
space (virtual memory). They can also communicate with each other and other processes.
Every thread has its own stack of execution and scheduled for execution by kernel
separately. IOS has the capability to execute multiple programs parallel but most of the
execution is done in background and does not require continuous processing. The
application that runs in foreground keeps the processor and other resources busy.
 THREADING PACKAGES
Applications may require creation of threads. IOS supports thread
management and synchronization along with other new technologies. The
technologies used to manage thread in iOS can be POSIX threads or Cocoa threads.
POSIX threads are based on C language. This must be used when application
needs to be designed for multiple platforms. Here threads are managed using pthread
library. Communication between threads can be done using ports, shared memory or
conditions. For Cocoa applications, threads are created using NSThread class. It
allows detached thread to be created. Detached thread is the one in which system
automatically reclaims thread’s resources when it terminates.
 THREADS ALTERNATIVES
Threadsarelowleveldoingconcurrencyandmanagingsynchronizationbecomesdi
fficult for application development. Also, the use of thread adds processor and
memory overheads. iOS henceoffersalternativesto thread programming.
Executionofconcurrent tasks or processes on iOS is managed by asynchronous
designing approach like traditional thread approach. Applications should only define
specific tasks instead of creating threads as threads are low level and should leave it
to system. Threads when managed by system, gives scalability to applications. The
various techniques provided by iOS to manage tasks asynchronously are:
o GRAND CENTRAL DISPATCH (GCD)
In this approach user only defines the task to be done and add it to the
appropriate dispatch queue. GCD then creates threads as needed and
schedules them. Since in this approach thread management and execution is
done by system, it is more efficient than traditional threads approach.
o OPERATION QUEUES
They are similar to dispatch queue and are object-C objects. User
defines the task to execute and add it to operation queue. Scheduling and
execution are then done by operation queue.
o DISPATCH QUEUES
Dispatch queue are used for execution of customized tasks. It
executes the task serially or concurrently in first-in first-out order. Serial
dispatcher waits for the task to complete before de-queuing, whereas
concurrent dispatcher does not wait for the tasks to nish before starting new
tasks.
o Operation Queues:
In operation queues the order of execution of task is dependent upon
many factors. One such factor is the dependence of one task on the
completion of another task. User when defining a task should also configure
dependency.
The various advantages of using dispatch and operation queues in place of
threads offer various advantages:
1) No need to store thread stack hence reduces memory requirements
2) User need not to configure and manage threads.
3) User need not to schedule threads.
4) It is easy to write code as compared to threads.

iCloud CONTAINER
iCloud service allows user to store their documents, photos, files, etc. to be stored in
cloud. Users when require can download these from their devices or share with other users.
iOS allows users data be automatically backed up in cloud through this service. This feature
is available in iOS 7 onwards. iCloud container is used to store files for apps that use iCloud.
Files and folders can be created by apps in the same way as local file folders are created.
Files and their attributes are copied to iCloud. Primary iCloud container ofapps stores native
files. Within each container two subdirectories – documents and data are present. Files
present within document subdirectory are visible to user as separate document which can be
individually deleted. Whereas files not within document subdirectory is displayed as single
entity in iCloud user interface called data.

IDENTIFICATION OF FILE TYPE


To identify the type of file, two techniques are used in iOS-
1) UTIs – UNIFORM TYPE IDENTIFIER: UTIs is a string that identifies class
entities uniquely. For all types of data and service it provides consistent
identifiers. Not only files but they can also represent folders or directories in a
flexible manner. They are used for identifying types of pasteboard. Some of the
examples are:
o Public.jpeg - it represents a public type UTI identifying jpeg image data.
o com.apple.bundle - it represents an Apple type identifying bundle directory.
o com.apple.application-bundle- it represents anAppletype identifying bundled
app.

2) FILENAME EXTENSION: It is a character string following filename and a


period (.). Each extension represents a specific type of file. For example,
filename with .png represents an image file. Also, period is a valid character for
filename, hence only the string after last period is considered as extension to
identify type.

SECURITY OF FILE SYSTEM


1) SANDBOX ENVIRONMENT
Applications during installation are automatically placed in a sandbox environment
in iOS. Sandbox does not allow apps to write data into locations to which user
should not write to. Every sandbox is created with few containers to which user can
write. One app cannot write to containers of other apps or most directories outside
their sandbox. Hence security ofapps and data is maintained by restricting the access.

2) FILE ACCESS CONTROL


File access control in iOS is maintained by two techniques – ACL& BSD. System
assigns ACL and BSD permission to files created by apps.

i) ACCESS CONTROL LIST


Access control list is a list of control details which gives complete
information of what operations can or cannot be done to a directory or file
and by which users. Hence it allows different level of access writes to
different user.

ii) BSD
In BSD instead of giving access writes to individual users, it allows
access to be given on the basis of class of users. There exist three classes of
users – owner of data or file, group of users, all other users.

iii) ENCRYPTION
iOS allows files on disk to be encrypted. Files that are needed to be
encrypted can be designated by apps. When a device containing encrypted
data is unlocked by user, a decryption key is generated by system to enable
access to file. Whereas, when user locks the device, to prevent unauthorized
access, the decryption key is destroyed by the system.
CASE STUDY – VMWARE WORKSTATION

INTRODUCTION
VMware Workstation includes Type 2 hypervisors. Unlike a Type 1 hypervisor,
which replaces the underlying OS altogether, a Type 2 hypervisor runs as an application on
the desktop OS and lets desktop users run a second OS atop their main (host) OS.
VMware Workstation comes in two flavors:
 Workstation Player is a free version that supports a single guest OS.

 Workstation Pro supports multiple guest operating systems and integrates with
VMware's enterprise virtualization management tools.

HOW TO INSTALL VMWARE TOOLS


There’s only one thing better than having a second OS on your desktop computer:
having a second OS that can exchange data with the first. That’s where VMware Tools
comes in. It is a crucial part of any VMware Workstation environment. It enables the guest
OS running within the Type 2 hypervisor to work better with the host OS.
The benefits of installing VMware Tools include faster graphics performance and support
for shared folders between the guest and host OS. You can use it to drag and drop files and
to cut and paste between the two operating systems.
To install VMware Tools, click VM and then Install VMware Tools from the VMware
Workstation menu. VMWare Workstation then mounts a virtual CD-ROM drive in the guest
OS that contains the VMware Tools installer. You then access the CD-ROM image from
within the guest OS and run the installer.
VMware’s Type 2 hypervisors compete with others on the market, including the following:

 VMware vs. VirtualBox: VirtualBox is a Type 2 hypervisor produced by Oracle-


owned Innotek that competes with VMware Workstation. It is a free, open-source
product that allows you to install and use another OS on top of the one already on
your desktop or laptop. You can install VMware's products on Linux and Windows.
VirtualBox supports Linux, Windows, Solaris, and FreeBSD as host operating
systems. Each product has its strengths and relative weaknesses in different areas.
VMware's products offer better support for 3D graphics, while VirtualBox supports
more virtual disk images, which are files that contain virtual machine data.

 VMware vs. Parallels: Parallels is a Type 2 hypervisor dedicated to running guest


operating systems on the macOS platform. It competes with VMware Fusion.
VMware Fusion is available for a single one-off fee, but you can only license
Parallels via a subscription model.
VIRTUAL DESKTOP INTEGRATION
VMware offers a third model that sits somewhere between the server and desktop
virtualization above—virtual desktop integration (VDI). VDI virtualizes desktop operating
systems on a server.
VDI offers centralized desktop management, letting you configure and troubleshoot
desktop operating systems without remote access or on-site visits. Users can access their
applications and data from any device, anywhere, without the need to invest in expensive,
high-powered client endpoint equipment. Sensitive data secure never leaves the server.

VMware Horizon
VMware Horizon is VMware's suite of VDI tools. It supports both Windows and
Linux desktops. You can run your virtual desktops on your own premises or use Horizon
Cloud to run them in multiple hosted cloud environments.
The Horizon suite includes Horizon Apps, a platform that lets you create your own
custom app store for enterprise users to run on their virtual desktops. Your users can access
a mixture of on-premise, SaaS, and mobile applications using a single set of login
credentials.
Explore the benefits of virtual desktop integration with VMware Horizon on IBM
Cloud.
vSphere
VMware vSphere (link resides outside IBM) is VMware’s enterprise virtualization
platform, including both the ESXi hypervisor software and the vCenter Server management
platform for managing multiple hypervisors.
vSphere is available in three configurations: Standard, Enterprise Class, and
Platinum. Each support policy-driven virtual machine storage, live workload migration, and
built-in cybersecurity features. The higher-end options include VM-level encryption,
integrated container management, load-balancing, and centralized network management.
Platinum alone supports automated responses to security threats and integration with third-
party security operations tools.

vCenter
One of vSphere’s important components is vCenter Server (link resides outside
IBM). This is the management component of vSphere. It allows you to manage virtual
machine deployments across a large collection of host servers. It assigns virtual machines to
hosts, allocates resources for them, monitors performance, and automates workflow. This
tool can be used to manage user privileges based on a user’s own policies.
VCenter Server has three main components:
 vSphere Web Client is the platform's user-interface, providing administrators with
browser-based access to all functions
 VCenter Server Database is the data repository for the product. It stores data
necessary for server hosts to run hypervisors and virtual machines.
 VCenter Single Sign-On lets you access the entire vSphere infrastructure with a
single login.
CLUSTERING:
Using a hypervisor on a host server will maximize your use of that hardware, but
most enterprises users will need more VMs than they can fit on a single physical server.
That’s where VMWare’s clustering technology comes in.
VMware shares resources between hosts by grouping them into a cluster and treating
them as a single machine. You can then use VMware’s clustering technology to pool
hardware resources between the hypervisors running on each host in the cluster. When
adding a VM to a cluster, you can give it access to these pooled resources. There may be
many clusters in a VMware-powered enterprise.
VMware allows you to create and manage clusters within its vSphere environment.
A cluster supports many vSphere features, including workload balancing, high availability,
and fault-tolerant resilience.
VMware clustering gives you access to several VMware functions to make your
virtual infrastructure run smoothly and reliably:
VMware HA
VMware’s vSphere High Availability (HA) (link resides outside IBM) solution lets
you switch virtual machines between physical hosts if the underlying hardware fails. It
monitors the cluster and if it detects a hardware failure, it restarts its VMs on alternate hosts.
vSphere HA designates one host in a cluster as the “master,” the others are called
“slaves.” The master communicates with vCenter Server, reporting back on the state of
protected VMs and slave hosts.
VMware Fault Tolerance
While vSphere HA provides rapid recovery from outages, you can still expect downtime
while it moves and restarts a VM. If you need more protection for mission-critical
applications, vSphere Full Tolerance (link resides outside IBM) offers a higher level of
availability. It promises no loss of data, transactions, or connections.
vSphere Fault Tolerance works by running a primary and secondary VM on separate hosts
in the cluster and ensuring that they are identical at any point. If either of their hosts fails,
the remaining host continues operating and vSphere Fault Tolerance creates a new
secondary VM, reestablishing redundancy. vSphere automates the whole process.
VMware DRS
If you allow many VMs to run unmanaged across your host machines, you will get into
trouble. Some VMs will be more demanding on CPU and memory resources than others.
This can create unbalanced workloads, with hosts handling more than their share of work
while others sit idle. VMware Distributed Resource Scheduling (DRS) (link resides outside
IBM) solves that problem by balancing workloads between different ESXi hypervisors.
DRS, a feature of vSphere Enterprise Plus, works within a cluster of ESXi hosts that are
sharing resources. It monitors host CPU and RAM usage and moves the VMs between them
to avoid overworked and underused hosts. You can set these allocation policies yourself to
reallocate resources aggressively or to rebalance less often.
VIRTUALIZING THE REST OF THE DATA CENTER
VMware made a name for itself virtualizing servers and then desktop operating systems. In
2012, it announced plans to virtualize and automate everything in the data center in a
concept called the software-defined data center (SDDC).

VMware's SDDC elements include the following:


VMware NSX
VMware NSX is a network virtualization product that allows you to define and control your
IT network logically in software. You can consolidate network functions such as switching,
routing, traffic load balancing, and firewalls into hypervisors running on x86 computers.
You can manage these functions together from a single screen rather than manually
configuring different hardware across different interfaces, and you can also apply software-
based policies to automate network functions. It is the network component of VMware’s
SDDC that brings the same virtualization benefits to networking, software, and computing
functions.
The product supports multiple environments, including your data center, private cloud, and
public hosted clouds. This makes it easier for your network to support cloud-native apps that
rely on container environments and microservices.
VMware vSAN
VMware vSAN is part of VMware’s storage virtualization solution. It creates a software
interface between VMs and physical storage devices. This software—part of the ESXi
hypervisor—represents physical storage devices as a single pool of shared storage,
accessible by machines in the same cluster.
Using VMware vSAN, your VMs can use storage on any computer in a cluster rather than
relying only on a single computer, which might run out of storage. It also avoids wasting a
physical computer's storage if the VMs running on that computer don't use it. VMs running
on other hosts can use its storage, too.
VSAN integrates with vSphere to create a storage pool for management tasks, such as high
availability, workload migration, and workload balancing. Custom policies give you full
control over how vSphere uses shared storage.
VMware Cloud
VMware offers several products and services under the VMware Cloud banner. VMware
Cloud Foundation, an integrated software suite supporting hybrid cloud operations, includes
a range of services for software-defined computing, storage, networking, and security, and it
is available as a service from a variety of cloud providers. You can deploy it in a private
cloud environment via vSAN Ready Node, a validated server configuration provided by an
OEM working with VMware.
VMware HCX (Service)
VMware HCX is a component of VMware Cloud that helps companies to use a mixture of
computing environments. This gives IT teams the functionality they want at the right cost
and enables them to keep more sensitive data on their own computers. The challenge is
getting these VMs to work together across these different environments.
HCX is VMware's answer to this hybrid cloud complexity. It is a software as a service
(SaaS) offering that lets you manage multiple vSphere instances across different
environments, ranging from on-premise data centers to hosted cloud environments.
Formerly called Hybrid Cloud Extension and NSX Hybrid Connect, HCX abstracts your
vSphere environment so that the VMs it manages appear to have the same IP address—no
matter where they run. HCX uses an optimized wide-area network (WAN) connection to
extend on-premise applications to the cloud without reconfiguration. This allows you to call
on extra computing power from the cloud to maintain the performance of on-premise
applications when computing demand exceeds on-premise physical resources.
You can often see this situation occur in retail. A spike in e-commerce demand might use up
all your data center resources. You can keep the orders flowing and avoid frustrated
customers by calling on computing resources in the cloud.
HCX lets you replicate your data to a cloud-based vSphere instance for disaster recovery.
Should you need to switch to a standby server or system if your on-premise infrastructure
becomes unavailable, you can do so without reconfiguring IP addresses. Learn more about
VMware HCX on IBM Cloud in our Architecture Center.

VMWARE CONTAINERS
Developers increasingly use containers as an alternative to VMs. Like VMs, they are virtual
environments containing applications abstracted from the physical hardware. However,
containers share the underlying host OS kernel instead of virtualizing an entire OS as VMs
do.
Containers offer more agility and use physical computing power more efficiently than VMs,
but they are not suitable for all cases. You might want to develop an entirely new application
that divides small pieces of functionality called microservices into separate containers,
making application development and maintenance more agile. On the other hand, a legacy
application written to run as a single binary program might be more suitable running in a
VM that mirrors the environment it is used to. You can take advantage of containers and
VMs together using the VMware’s vSphere Integrated Containers (link resides outside IBM)
feature, which bridges the gap between the two by allowing containers to run in VMware
environments. It comprises three components:
 vSphere Integrated Container Engine lets developers run containerized apps based
on the popular Docker container format alongside VMs on the same vSphere
infrastructure.
 Project Harbor is an enterprise container registry that lets developers store and
distribute container images so that other developers can reuse them.
 Project Admiral is a management portal that lets development teams provision and
manage containers.
AIRWATCH
AirWatch (link resides outside IBM) is a VMware division focusing on enterprise mobility
management. Its technology is the basis for VMware’s Workspace ONE Unified Endpoint
Management product, which lets you manage endpoints ranging from desktops through to
small-footprint Internet of Things (IoT) devices using a single management console.
Endpoints are security vulnerabilities for companies. Attackers can gain access to the whole
network by infecting a single endpoint with malware. Endpoints are also vulnerable to
physical theft, making the data on them vulnerable. Managing all endpoints centrally, even
when they are not on the office network, helps administrators ensure that the endpoints are
properly secured and encrypted.
The endpoint management product supports a range of operating systems, from Android
through to MacOS and even IoT-focused systems such as QNX. You can configure usage
policies and security settings for each device on the network.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy