In: Computer Science
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[5].
There will be five users running concurrently and each will execute 5 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).
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 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” 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:
Define all semaphores that you need according to the number of buffers used.
Each user will make 5 system calls to initiate I/O operations
DOIO will create 25 IORB
The sum of the I/O operations executed by drivers must add up 25. You will need a shared variable to control the total number of I/O operations because it is not known before hand the numbers of I/O operations initiated by each Device driver.
Once Drivers have served all request they have to signal DOIO.
Once DOIO receives signasl from Drivers indicating all request have been served. DOIO will shut down both Disks.
Project Direction
You will write the program C-- based on the BACI interpreter that you used in programming project 1.
Test your solution
You must run and test your solution for correctness, as well as, comment on the code and the expected results. If this were a task for an employer, you would be expected to follow company policy, including naming, conventions, and syntax.
Project Submission
What to submit?
Submit the source code(.cm file) with comments and the output file (.txt) showing the results.
Example for the print out of results:
User 1 executes system call SIO or DOIO
DOIO assembles IORB and inserts it in IORQ for user 1
User 2 executes system call SIO or DOIO
Driver initiates I/O operation for user 1
User 3 executes system call SIO or DOIO
User 4 executes system call SIO or DOIO
DOIO assembles IORB and inserts it in IORQ for user 2
Disk Completes I/O operation (disk does not know what process initiated the I/O operation)
Driver signal user 1 (operation complete)
User 1 executes system call SIO or DOIO
DOIO assembles IORB and inserts it in IORQ
And so on…
List of variables and semaphores to be used in the program:
SEMAPHORES
FUNCTIONS
#include<stdlib.h>
#include<stdio.h>
#include<ctype.h>
#include <semaphore.h>
#include <sys/types.h>
#include <pthread.h>
#include <unistd.h>
const int COUNTER = 5; //Number of
I/O requests for each user
int TOTAL = 25;
//Total 25 IORB
int DRIVERS = 2; //No of device
drivers
int USERS = 5;
//Total number of I/O requests
//Total number of Drivers
//Number of Users //Semaphores for User
int
main ()
{
sem_t fullUser;
sem_t ioReq;
//binarysemaphore mutexUser; //User buffer at max
sem_t mutexUser;
sem_init (&mutexUser, 0, 1); /* initialize mutex to
1 - binary semaphore */
//User buffer at empty
//User buffer protect //Semaphores for Driver 1
sem_t fullDriver1[DRIVERS];
sem_t reqPend[DRIVERS];
//binarysemAaphore mutexDriver1[DRIVERS]; //Driver 1 buffer at
max
sem_t mutexDriver1;
/* Create the mutexDriver semaphore and initialize to DRIVERS
buffer size */
sem_init (&mutexDriver1, 0, DRIVERS);
//Driver 1 buffer at empty
//Driver 1 buffer protect //Semaphores for Driver 2
sem_t fullDriver2[DRIVERS];
sem_t reqPend2[DRIVERS];
//binarysemaphore mutexDriver2[DRIVERS]; //Driver 2 buffer at
max
sem_t mutexDriver2;
sem_init (&mutexDriver2, 0, DRIVERS);
//Driver 2 buffer at empty
//Driver 2 protect //Semaphores for Disk 1
sem_t fullDisk1[DRIVERS];
sem_t physicalio1[DRIVERS];
//binarysemaphore mutexDisk1[DRIVERS]; //Disk buffer at max
sem_t mutexDisk1;
sem_init (&mutexDisk1, 0, DRIVERS);
//Disk buffer at empty
//Disk buffer protect //Semaphores for Disk 2
sem_t physicalio2[DRIVERS];
sem_t fullDisk2[DRIVERS];
//binarysemaphore mutexDisk2[DRIVERS]; //Disk buffer at empty
sem_t mutexDisk2;
sem_init (&mutexDisk2, 0, DRIVERS);
//Disk buffer at max
//Disk buffer protect //Other semaphores
//binarysemaphore reqService[USERS];
sem_t reqService;
sem_init (&reqService, 0, USERS);
//binarysemaphore opComplete1[DRIVERS];
sem_t opComplete1;
sem_init (&opComplete1, 0, DRIVERS);
//binarysem opComplete2[DRIVERS];
sem_t opComplete2;
sem_init (&opComplete2, 0, DRIVERS);
//binarysem print; //I/O request print
sem_t print;
sem_init (&print, 0, 1);
//Disk1 protection
//Disk 2 protection
//Print protection
int idUser;
int addrUser;
int devUser;
int idIorq[DRIVERS];
int addrIorq[DRIVERS];
int pio[DRIVERS];
int countdriver = 0;
int countdisk = 0; //User/Doio id
buffer
//User/Doio address buffer
//User/Doio device buffer
//Doio/Driver user id buffer
//Doio/Driver address id buffer
//Driver/Disk
//Counter for Driver
//Counter for Disk
void User (int id)
{
int i, addr, dev; //Local variables
used
for (i = 0; i <= COUNTER; i++)
{
//Loop through the number of requests
addr = rand () % 200 + 1;
//Generating random I/O information
dev = rand () % 2;
//Generating random Driver assignment
p (fullUser);
//Decrement available buffer locations between User and DOIO
p (mutexUser);
//Exclusive access to I/O request idUser = id;
//Passing user id to shared resource
addrUser = addr;
//Passing address to shared resource
devUser = dev;
//Passing driver id to shared resource
p (print);
//Gaining control of the printer
/*cout << "User " <<
id << "executes system call SIO or
DOIO" << endl; */
v (print);
printf ("executes system call SIO or DOIO");
v (mutexUser);
//Released control of the printer
//Release editting control of the I/O v(ioReq); //Inform DOIO that
the request is p(reqService[id]); //Wait for completion of I/O
request pending operation.
}
}
void Doio ()
{
int j, idIorb, addrIorb, devIorb;
for (j = 0; j <= TOTAL; j++)
{
p (ioReq);
//sent a request
p (mutexUser);
//request
idIorb = idUser;
addrIorb = addrUser;
devIorb = devUser;
v (mutexUser);
//I/O request
v (fullUser);
//buffer locations between User and DOIO
// //Local variables used
//For loop that goes
//Checking to see if user
//Exclusive access to I/O
//Copying user ID into DOIO
//Copying address into DOIO
//Copying driver ID into DOIO
//Releasing editting control of
//Incrementing available Ending consuming process
p(fullDriver1[devIorb]);
//Decrementing available buffer locations
p (mutexDriver1[devIorb]);
//Exclusive access to I/O request
idIorq[devIorb] = idIorb;
//Passing user to shared source
addrIorq[devIorb] = addrIorb;
//Passing address information to shared resource
v (mutexDriver1[devIorb]);
//Releasing editing control of I/O request
v (reqPend[devIorb]);
//Inform Driver request is pending
p (print);
//Gain control of printer
/*cout << "DOIO assembles IORB and inserts
it into IORQ for User " <<
idIorb << endl;*/
printf ("DOIO assembles IORB and inserts it into IORQ
for User");
v (print);
//Release control of printer
// Begin consuming process
p (ioReq);
//request
p (mutexUser);
//request
idIorb = idUser;
addrIorb = addrUser;
devIorb = devUser; //Checking to see if
user sent a
//Exclusive access to I/O
//Copying user into DOIO
//Copying address into DOIO
//Copying driver ID into DOIO request v(mutexUser); //Releasing
control of I/O v(fullUser);
//Incrementing available buffer locations
//Begin producing process
p (fullDriver2[devIorb]);
//Decrementing available buffer location
p (mutexDriver2[devIorb]);
//Exclusive access to I/O request
idIorq[devIorb] = idIorb;
//Passing user into shared source
addrIorq[devIorb] = addrIorb;
//Passing addr into shared source
/*cout << "DOIO assembles IORB and inserts
it in IORQ2 for User " <<
idIorb << endl;*/
v (mutexDriver2[devIorb]);
//Releasing control of I/O request
v (reqPend2[devIorb]);
//Inform driver request is pending
}
}
void Driver1 (int id)
{
int idDriver, addrDriver, k;
//Local variables
p (reqPend[id]);
//Check to see if there is a request from DOIO
while (countdriver <= 25)
{
//Loop through the requests
if (countdriver == 25)
{
//Check for out of bounds
v (reqPend2[k]);
break;
}
p (mutexDriver1[id]);
//Gain exclusive editting access to IORQ
idDriver = idIorq[id];
//Copy user ID into Driver
addrDriver = addrIorq[id];
//Copy address into Driver
v (mutexDriver1[id]);
//Release editting control of I/O request
v (fullDriver1[id]);
//Increment available buffer location by 1
p (print);
//Control of printer
/*cout << "Driver 1 initiates I/O operation
for user " << idDriver
<<
endl;*/
printf ("Driver 1 initiates I/O operation for
user");
v (print);
//Release control of printer
p (fullDisk1[id]);
//Decrement available buffer locations
p (mutexDisk1[id]);
//Gain access to Disk request
pio[id] = addrDriver;
//Pass adress to shared resource
p (print);
/*cout << "Driver 1 signals User "
<< idDriver << "that the
operation
is complete." << endl;*/
printf ("operation complete");
countdriver++;
v (print);
v (mutexDisk1[id]);
//Release control of Disk request
v (physicalio1[id]);
//Inform disk request is pending
p (opComplete1[id]);
//Waiting for disk operation to complete
v (reqService[idDriver]);
//Inform user request is complete } if ( countdriver == 25 )
{
v (reqPend[k]);
break;
}
//Check for out of bounds
}
void Driver2 (int id)
{
int idDriver2, addrDriver2, i = 0;
//Local variables
p (reqPend2[id]);
//Check to see if there is a request from DOIO
while (countdriver <= 25)
{
//Loop through the requests
if (countdriver == 25)
{
//Check for out of bounds
v (reqPend[i]);
break;
}
p (mutexDriver2[id]);
//Gain exclusive access to I/O request
idDriver2 = idIorq[id];
//Copy user ID into Driver
addrDriver2 = addrIorq[id];
//Copy address into Driver
v (mutexDriver2[id]);
//Release control of Disk Request
v (fullDriver2[id]);
//Increment available buffer location
p (print);
//Access printer
/*cout << "Driver 2 initiates I/O operation
for user " << idDriver2
<<
endl;*/
v (print);
printf ("Driver 2 initiates I/O operation for
user");
//Release access to printer
p (fullDisk2[id]);
//Decerement available buffer locations
p (mutexDisk2[id]);
//Gain access to Disk 2 request
pio[id] = addrDriver2;
//Pass address to a shared resource
p (print);
/*cout << "Driver 2 signals User "
<< idDriver2 << "that the
operation
is complete." << endl;*/
printf ("request served");
countdriver++;
v (print);
v (mutexDisk2[id]);
//Release control of disk request
v (physicalio2[id]);
//Inform disk 2 request is pending
p (opComplete2[id]);
//Waiting for disk 2 to complete
v (reqService[idDriver2]);
//Inform user the request is complete
if (countdriver == 25)
{
v (reqPend[i]);
break;
}
}
}
void Disk1 (int id)
{
int i, seek; //Check for out of
while(countdisk < 25){
p (physicalio1[id]);
//Decrement available buffer locations
p (mutexDisk1[id]);
//Gain exclusive access to I/O request
seek = pio[id];
//Grabbing the address from shared resource
v (mutexDisk1[id]);
//Releasing control of Disk 1
v (fullDisk1[id]);
//Increment available buffer location
for (i = 1; i <= seek; i++)
{
}
//Dummy loop that iterates from i to seek
p (print);
//Gain access to the printer
/*cout << "Disk 1 Completes I/O
operation." << endl;*/
v (print);
//Release acess to the printer.
countdisk++;
v (opComplete1[id]);
//Inform Driver operation is complete
}
}
void
Disk2 (int id)
{
int i, seek;
//Local variables while(countdisk < 25){
//Loop through the requests
p (physicalio2[id]);
//Decrement available buffer locations
p (mutexDisk2[id]);
//Gain exclusive access to I/O request
seek = pio[id];
//Grabbing the address from shared resources
v (mutexDisk2[id]);
//Releasing control of Disk 2
v (fullDisk2[id]);
//Increment available buffer location
for (i = 1; i <= seek; i++)
{
}
//Dummy loop that iterates from i to seek
/*cout << "Disk 2 Completes I/O
operation." << endl;*/
printf ("Disk 2 Completes I/O operation") countdisk++;
v (opComplete2[id]);
//Inform Driver operation is complete
}
}
int z = 0;
initialsem (fullUser, 1);
initialsem (ioReq, 0);
initialsem (mutexUser, 1);
for (z = 0; z & lt; USERS; z++)
{
initialsem (reqService[z], 0);
}
for (z = 0; z <= DRIVERS; z++)
{
initialsem (fullDriver1[z], 1);
initialsem (reqPend[z], 0);
initialsem (mutexDriver1[z], 1);
initialsem (fullDriver2[z], 1);
initialsem (reqPend2[z], 0);
initialsem (mutexDriver1[z], 1);
initialsem (fullDisk1[z], 1);
initialsem (physicalio1[z], 0);
initialsem (mutexDisk1[z], 1);
initialsem (fullDisk2[z], 1);
initialsem (physicalio2[z], 0);
initialsem (mutexDisk2[z], 1);
initialsem (opComplete1[z], 0);
initialsem (opComplete2[z], 0);
}
initialsem (print, 1);
cobegin
{
User (0);
User (1);
User (2);
User (3);
User (4);
Doio ();
Driver1 (0);
Driver2 (0);
Disk1 (0);
Disk2 (0);
}
return 0;
}