Você está na página 1de 23

IPC Problems

In this section of the tutorial module, we look at two different interprocess communication problems. In each subsection, the problem is presented, followed by explanations of possible solutions using each of the three types of interprocess communication we have discussed. THE AQUA LINE Producer/Consumer Problems Readers/Writers Problems

IPC Home

Subway Page

Solution Demos Map Types

The Producer Consumer Problem


The producer-consumer problem illustrates the need for synchronization in systems where many processes share a resource. In the problem, two processes share a fixed-size buffer. One process produces information and puts it in the buffer, while the other process consumes information from the buffer. These processes do not take turns accessing the buffer, they both work concurrently. Herein lies the problem. What happens if the producer tries to put an item into a full buffer? What happens if the consumer tries to take an item from an empty buffer? In order to synchronize these processes, we will block the producer when the buffer is full, and we will block the consumer when the buffer is empty. So the two processes, Producer and Consumer, should work as follows:

(1) The producer must first create a new widget. (2) Then, it checks to see if the buffer is full. If it is, the producer will put itself to sleep until the consumer wakes it up. A "wakeup" will come if the consumer finds the buffer empty.(3) Next, the producer puts the new widget in the buffer. If the producer goes to sleep in step (2), it will not wake up until the buffer is empty, so the buffer will never overflow. (4) Then, the producer checks to see if the buffer is empty. If it is, the producer assumes that the consumer is sleeping, an so it will wake the consumer. Keep in mind that between any of these steps, an interrupt might occur, allowing the consumer to run.

(1) The consumer checks to see if the buffer is empty. If so, the consumer will put itself to sleep until the producer wakes it up. A "wakeup" will occur if the producer finds the buffer empty after it puts an item into the buffer. (2) Then, the consumer will remove a widget from the buffer. The consumer will never try to remove a widget from an empty buffer because it will not wake up until the buffer is full.(3) If the buffer was full before it removed the widget, the consumer will wake the producer. (4) Finally, the consumer will consume the widget. As was the case with the producer, an interrupt could occur between any of these steps, allowing the producer to run.

The code might look like this:

BufferSize = 3; count = 0; Producer() { int widget; WHILE (true) { make_new(widget); IF(count==BufferSize) Sleep(); put_item(widget); count = count + 1; IF (count==1) Wakeup(Consumer); } } Consumer() { int widget; WHILE(true) { IF(count==0) Sleep(); remove_item(widget); count = count + 1; IF(count==N-1) Wakeup(Producer); Consume_item(widget); } } In the next three sections, the Purple Line, we will discuss solutions to this problem using each of the three methods introduced in the Solution Types section:

// loop forever // create a new widget to put in the buffer // if the buffer is full, sleep // put the item in the buffer // increment count of items // if the buffer was previously empty, wake // the consumer

// loop forever // if the buffer is empty, sleep // take an item from the buffer // decrement count of items // if buffer was previously full, wake // the producer // consume the item

Semaphores Monitors Message Passing

IPC Home Page

Subway Map

Problems

Readers/ Writers

Solution to the Producer-Consumer problem using Semaphores


One problem with implementing a Sleep and Wakeup policy is the potential for losing Wakeups. Semaphores solve the problem of lost wakeups. In the Producer-Consumer problem, semaphores are used for two purposes:
q q

mutual exclusion and synchronization.

In the following example there are three semaphores. Full, used for counting the number of slots that are full; empty, used for counting the number of slots that are empty; and mutex, used to enforce mutual exclusion. BufferSize = 3; semaphore mutex = 1; semaphore empty = BufferSize; semaphore full = 0; Producer() { // Controls access to critical section // counts number of empty buffer slots // counts number of full buffer slots

int widget; while (TRUE) { make_new(widget); down(&empty); down(&mutex); put_item(widget); up(&mutex); up(&full); } } Consumer() { int widget; while (TRUE) { down(&full); down(&mutex); remove_item(widget); up(&mutex); up(&empty); consume_item(widget); } } // // // // // // // loop forever decrement the full semaphore enter critical section take a widget from the buffer leave critical section increment the empty semaphore consume the item // // // // // // // loop forever create a new widget to put in the buffer decrement the empty semaphore enter critical section put widget in buffer leave critical section increment the full semaphore

IPC Home Subway Problems Page Map

Producer/ Monitors Consumer

Solution to the Producer-Consumer problem using Monitors


Monitors make solving the producer-consumer a little easier. Mutual exclusion is achieved by placing the critical section of a program inside a monitor. In the code below, the critical sections of the producer and consumer are inside the monitor ProducerConsumer. Once inside the monitor, a process is blocked by the Wait and Signal primitives if it cannot continue. monitor ProducerConsumer condition full, empty; int count; procedure enter(); { if (count == N) wait(full); put_item(widget); count = count + 1; if (count == 1) signal(empty); } procedure remove(); {

// // // //

if buffer is full, block put item in buffer increment count of full slots if buffer was empty, wake consumer

if (count == 0) wait(empty); remove_item(widget); count = count - 1; if (count == N-1) signal(full); } count = 0; end monitor; Producer(); { while (TRUE) { make_item(widget); ProducerConsumer.enter; } } Consumer(); { while (TRUE) { ProducerConsumer.remove; consume_item; } }

// // // //

if buffer is empty, block remove item from buffer decrement count of full slots if buffer was full, wake producer

// make a new item // call enter function in monitor

// call remove function in monitor // consume an item

IPC Home Page

Subway Map

Problems

Producer/ Consumer

Message Passing

Solution to the Producer-Consumer problem using Message Passing


Message Passing allows us to solve the Producer-Consumer problem on distributed systems. In the problem below, an actual buffer does not exit. Instead, the producer and consumer pass messages to each other. These messages can contain the items which, in the previous examples, were placed in a buffer. They can also contain empty messages, meaning that a slot in the "buffer" is ready to receive an new item. In this example, a buffer size of four has been chosen. The Consumer begins the process by sending four empty messages to the producer. The producer creates a new item for each empty message it receives, then it goes to sleep. The producer will not create a new item unless it first receives an empty message. The consumer waits for messages from the producer which contain the items. Once it consumes an item, it sends an empty message to the producer. Again, there is no real buffer, only a buffer size which dictates the number of items allowed to be produced.

BufferSize = 4; Producer() { int widget; message m;

// message buffer

while (TRUE) { make_item(widget); receive(consumer, &m); build_message(&m, widget); send(consumer, &m); } } Consumer() { int widget; message m; for(0 to N) send(producer, &m); while (TRUE) { receive(producer, &m); extract_item(&m, widget); send(producer, &m); consume_item(widget); } }

// // // //

create a new item wait for an empty message to arrive make a message to send to the consumer send widget to consumer

// send N empty messages

// // // //

get message containing a widget take item out of message reply with an empty message consumer the item

IPC Home Page

Subway Map

Problems

Producer/ Consumer

The Readers and Writers Problem


The Readers and Writers problem is useful for modeling processes which are competing for a limited shared resource. A practical example of a Readers and Writers problem is an airline reservation system consisting of a huge data base with many processes that read and write the data. Reading information from the data base will not cause a problem since no data is changed. The problem lies in writing information to the data base. If no constraints are put on access to the data base, data may change at any moment. By the time a reading process displays the result of a request for information to the user, the actual data in the data base may have changed. What if, for instance, a process reads the number of available seats on a flight, finds a value of one, and reports it to the customer. Before the customer has a chance to make their reservation, another process makes a reservation for another customer, changing the number of available seats to zero. In the following pages, we will look at solutions to this problem using semaphores, monitors, and message passing. In the next three sections, the Orange Line, we will discuss solutions to this problem using each of the three methods mentioned in the Solution Types section: Semaphores Monitors Message Passing

IPC Home Page

Subway Map

Problems

Producer/ Consumer

Solution to the Readers and Writers problem using Semaphores


Semaphores can be used to restrict access to the database under certain conditions. In this example, semaphores are used to prevent any writing processes from changing information in the database while other processes are reading from the database.

semaphore mutex = 1; semaphore db = 1; int reader_count;

// Controls access to the reader count // Controls access to the database // The number of reading processes accessing the data

Reader() { while (TRUE) { // loop forever down(&mutex); // gain access to reader_count reader_count = reader_count + 1; // increment the reader_count if (reader_count == 1) down(&db); // if this is the first process to read the database, // a down on db is executed to prevent access

to the up(&mutex); read_db(); down(&mutex); reader_count = reader_count - 1; if (reader_count == 0) up(&db); the // database, allow writing process to access the data up(&mutex); reader_countuse_data(); critical) } Writer() { while (TRUE) { create_data(); critical) down(&db); write_db(); up(&db); } // allow other processes to access // use the data read from the database (non// // // // // database by a writing process allow other processes to access reader_count read the database gain access to reader_count decrement reader_count

// if there are no more processes reading from

// loop forever // create data to enter into database (non// gain access to the database // write information to the database // release exclusive access to the database

IPC Home

Subway

Problems

Readers/

Monitors

Page

Map

Writers

Solution to the Readers and Writers problem using Monitors


Monitors can be used to restrict access to the database. In this example, the read and write functions used by processes which access the database are in a monitor called ReadersWriters. If a process wants to write to the database, it must call the writeDatabase function. If a process wants to read from the database, it must call the readDatabase function. Remember that monitors use the primitives Wait and Signal to put processes to sleep and to wake them up again. In writeDatabase, the calling process will be put to sleep if the number of reading processes, stored in the variable count, is not zero. Upon exiting the readDatabase function, reading processes check to see if they should wake up a sleeping writing process. monitor ReadersWriters condition OKtoWrite, OKtoRead; int ReaderCount = 0; Boolean busy = false;

procedure StartRead() { if (busy) OKtoRead.wait;

// if database is not free, block

ReaderCount++; OKtoRead.signal(); } procedure EndRead() { ReaderCount-- ; if ( ReaderCount == 0 ) OKtoWrite.signal(); }

// increment reader ReaderCount

// decrement reader ReaderCount

procedure StartWrite() { if ( busy || ReaderCount != 0 ) OKtoWrite.wait(); busy = true; } procedure EndWrite() { busy = false; If (OKtoRead.Queue) OKtoRead.signal(); else OKtoWrite.signal(); } Reader() { while (TRUE) // loop forever { ReadersWriters.StartRead();

readDatabase(); ReadersWriters.EndRead(); } }

// call readDatabase function in monitor

Writer() { while (TRUE) // loop forever { make_data(&info); // create data to write ReaderWriters.StartWrite(); writeDatabase(); // call writeDatabase function in monitor ReadersWriters.EndWrite(); } }

IPC Home Page

Subway Map

Problems

Readers/ Writers

Message Passing

Solution to the Readers and Writers problem using Message Passing


In this solution to the Readers/Writers problem, Message Passing is used to prevent a writing process from writing into the database while another process is either reading or writing. The following solution assumes that readers and writers send their requests to a database server process that ensures that the above property holds.

Reader() { while (TRUE) { send (server, ReadRequest); receive (server, value); display (value); } } Writer() {

while (TRUE) { create_data (&value); send (server, WriteRequest, value); receive (server, WriteOk); } }

IPC Home Page

Subway Map

Problems

Readers/ Writers

Você também pode gostar