Page 57 - DCAP103_Principle of operating system
P. 57

Principles of Operating Systems



                   Notes         We may want to provide an environment that allows process cooperation for several reasons:
                                    •  Information sharing: Since several users may be interested in the same piece of information
                                      (for instance, a shared file), we must provide an environment to allow concurrent access
                                      to these types of resources.
                                    •  Computation speedup: If we want a particular task to run faster, we must break it into
                                      subtasks, each of which will be executing in parallel with the others. Such a speedup can
                                      be achieved only if the computer has multiple processing elements (such as CPUs or I/O
                                      channels).
                                    •  Modularity: We may want to construct the system in a modular fashion, dividing the
                                      system functions into separate processes or threads.
                                    •  Convenience: Even an individual user may have many tasks on which to work at one
                                      time. For instance, a user may be editing, printing, and compiling in parallel.

                                 Concurrent  execution  of  cooperating  processes  requires  mechanisms  that  allow  processes  to
                                 communicate with one another and to synchronize their actions.
                                 To  illustrate  the  concept  of  cooperating  processes,  let  us  consider  the  producer-consumer
                                 problem, which is a common paradigm for cooperating processes. A producer process produces
                                 information that is consumed by a consumer process. For example, a print program produces
                                 characters that are consumed by the printer driver. A compiler may produce assembly code,
                                 which is consumed by an assembler. The assembler, in turn, may produce object modules, which
                                 are consumed by the loader.
                                 To  allow  producer  and  consumer  processes  to  run  concurrently,  we  must  have  available  a
                                 buffer of items that can be filled by the producer and emptied by the consumer. A producer can
                                 produce one item while the consumer is consuming another item. The producer and consumer
                                 must be synchronized, so that the consumer does not try to consume an item that has not yet
                                 been produced. In this situation, the consumer must wait until an item is produced.
                                 The unbounded-buffer producer-consumer problem places no practical limit on the size
                                 of the buffer. The consumer may have to wait for new items, but the producer can always
                                 produce new items. The bounded-buffer producer consumer problem assumes a fixed buffer
                                 size. In this case, the consumer must wait if the buffer is empty, and the producer must
                                 wait if the buffer is full.

                                 The buffer may either be provided by the operating system through the use of an Inter Process
                                 Communication (IPC) facility or by explicitly coded by the application programmer with the use
                                 of shared memory. Let us illustrate a shared-memory solution to the bounded-buffer problem.
                                 The producer and consumer processes share the following variables:


                                 #define BUFFER-SIZE 10
                                 typedef s t r u c t {
                                 . . .
                                 ) item;
                                 item buffer [BUFFER-SIZE] ;
                                 int in = 0;
                                 i n t out = 0;


                                 The shared buffer is implemented as a circular array with two logical pointers—in and out. The
                                 variable in points to the next free position in the buffer; out points to the first full position in the
                                 buffer. The buffer is empty when in == out ; the buffer is full when ((in + 1) % BUFFERSIZE)



        50                                LOVELY PROFESSIONAL UNIVERSITY
   52   53   54   55   56   57   58   59   60   61   62