In: Computer Science
(Five Users - DOIO – Two Device drivers – Two Disks)
1.- In this assignment you will implement a simulation of the interaction of user programs with the OS to execute an I/O operation on two different devices.
User programs:
User programs will communicate with DOIO (OS) to request an I/O operation. (This will simulate a system call)
User programs will give to DOIO three parameters: User id, device number (dev is a random number in the range 1 and 2 that represents device one or device two) and an address (addr is a random number in the range 1 and 20.) (addr is an integer that represents a track number in the hard drive).
User programs will pass the parameters to DOIO through three buffers of size one each (bufid, bufdev, and bufaddr).
Once the parameters are stored in the buffers, user programs executes a p(request_served[ “index” ]) operation to wait for the completion of the I/O operation. You will need a semaphore array request_served[id].
There will be four users running concurrently and each will execute 4 I/O operations.
DOIO:
DOIO will collect and id, device(dev), and address(addr) from bufid, bufdev, and bufaddr to assemble the IORB.
DOIO will check on device number to decide which one of the two devices will get the IORB.
Once the device has been selected, DOIO will store the IORB (id and addr) into the two buffers that represent the IORQ (iorqid and iorqaddr) of the selected device. Notice that you need separate buffers (one for each device: iorqid and iorqaddr and iorqid2 and iorqaddr2). IORQ size four.
DOIO must wait to receive signals from Device drivers indicating that all request have been served. Then DOIO will shut down both Disks.
Device drivers (1 and 2):
Device drivers will collect an IORB (made up of id and addr) from iorqid and iorqaddr (or iorqid2 and iorqaddr2) and then initiate the physical I/O operation on the hard drive it controls and wait for the I/O operation to be completed: p(operation_complete).
The device driver initiates the physical I/O operation by storing addr into a buffer of length one. The buffer name is “pio” (physical I/O).
When the I/O operation completes a signal is received, the Device driver will identify the User that issued the I/O request using the id, and will signal the semaphore “request_served[id]” associated to the User.
When the last request has been served, both drivers have to signal DOIO to indicate that all requests have been handled and both drivers will emit a message: “Driver 1 (2) stops”
Disk (1 and 2):
The Disk processes simulates the access to a track in the hard drive.
The Disk process gets the addr from pio and stores it in a variable called “seek” and iterates in a dummy loop from 1 to “seek”.
Once out of the loop, disk will execute a v on the semaphore “operation_complete”
Disk will operate continuously until DOIO shuts them down.
Note:
Project Direction:
You will write the program C--based on the BACI interpreter
The below code might resolve the problem provided above. Please go through the code and try to understand the details of every line by which the code is invoking different modules and functions.
const int bufferSize = 5;
const int loopAmount = 25;
semaphore FULL1, FULL2, FULL3;
semaphore MUTEX1, MUTEX2, MUTEX3;
semaphore PRINT;
semaphore PIO, SIO;
semaphore operationComplete;
semaphore requestPending;
semaphore requestService[bufferSize];
int IORQid[bufferSize];
int IORQaddr[bufferSize];
int bufferAddress = 0, bufferID = 0, track = 0;
void User (int userID) {
int i, j, address = 0;
for(j = 0; j < bufferSize; j++){
address = random(i+1) % 200; /* notice the range of random number
is not same as the problem above */
p(FULL1);
p(MUTEX1);
bufferID = userID;
bufferAddress = address;
p(PRINT);
cout << "User " << userID + 1 << " executes
system call SIO" << endl;
v(PRINT);
v(MUTEX1);
v(SIO);
p(requestService[userID]);
}
}
void DOIO() {
int i = 0, tempID, tempAddr, index;
for (index = 0; index < loopAmount; index++){
p(SIO);
p(MUTEX1);
tempID = bufferID;
tempAddr = bufferAddress;
v(MUTEX1);
v(FULL1);
p(FULL2);
p(MUTEX2);
IORQid[i] = tempID;
IORQaddr[i] = tempAddr;
i = (i+1) % 5;
p(PRINT);
cout << "DOIO assembles IORB for user " << tempID + 1
<<
" and inserts it in IORQ" << endl;
v(PRINT);
v(MUTEX2);
v(requestPending);
}
}
void DeviceDriver() {
int j = 0, driverAddress = 0, driverID = 0, i;
for (i = 0; i < loopAmount; i++){
p(requestPending);
p(MUTEX2);
driverID = IORQid[j];
driverAddress = IORQaddr[j];
j = (j+1) % 5;
v(MUTEX2);
v(FULL2);
p(FULL3);
p(MUTEX3);
track = driverAddress;
v(MUTEX3);
v(PIO);
p(PRINT);
cout << "Driver initiates I/O operation for user " <<
driverID + 1<< endl;
v(PRINT);
p(operationComplete);
v(requestService[driverID]);
p(PRINT);
cout << "Driver signal user " << driverID + 1 <<"
to informed that I/O request is served."<< endl;
v(PRINT);
}
}
void Disk() {
int i = 0, seek = 0, diskAddress = 0, j;
for (j = 0; j < loopAmount; j++){
p(PIO);
p(MUTEX3);
seek = track;
v(MUTEX3);
diskAddress = seek * 20;
for (i = 1; i <= diskAddress; i++){} //Dummy Loop
v(operationComplete);
p(PRINT);
cout << "Disk signal driver(operation complete)" <<
endl;
v(PRINT);
v(FULL3);
}
}
main () {
initialsem (MUTEX1, 1);
initialsem (MUTEX2, 1);
initialsem (MUTEX3, 1);
initialsem (PRINT,1);
initialsem (FULL1, 1);
initialsem (FULL2, 5);
initialsem (FULL3, 1);
initialsem (SIO, 0);
initialsem (PIO, 0);
initialsem (requestPending, 0);
initialsem (operationComplete, 0);
initialsem (requestService[0], 0);
initialsem (requestService[1], 0);
initialsem (requestService[2], 0);
initialsem (requestService[3], 0);
initialsem (requestService[4], 0);
cobegin {
User(0);
User(1);
User(2);
User(3);
User(4);
DOIO();
DeviceDriver();
Disk();
}
}