LAB4OS
LAB4OS
SCXVCVSSS
SUBJECT: COMPUTER SCIENCE
ESSION:2024
2222202420
SUBMITTED BY
23-24
LAB:4
COURSE:OPERATING SYSTEM
INTERPROCESS COMMUNICATION
Inter-process communication (IPC) is an essential concept in modern operating systems that allow
processes to exchange data and synchronize activities. IPC mechanisms enable processes to work
together, share resources, and coordinate operations to achieve a common goal. In a world where
software applications are becoming more complex and systems are becoming more distributed,
understanding IPC is crucial for any software developer or system administrator.
1. SHARED MEMORY
PROBLEM STATEMENT :
There is one Producer and one Consumer in the producer-consumer problem.
1. PRODUCER
The producer process executes a set of statements int produce to create a data element and
stores it in the buffer.
2. CONSUMER
If the buffer has items, a consumer process executes a statement consume with the data
element as a parameter.
SOLUTION :
The problem arises because the process is not synchronized because of which the items
produced and consumed may not be consistent. In order to solve this problem, we use
semaphore for solving this problem i.e. problem of the critical section.
.
ALGORITHM FOR PRODUCER-CONSUMER
SETUP:
MUTEX: To make sure only one process accesses the buffer at a time.
FULL: To count how many items are currently in the buffer.
EMPTY: To count how many empty slots are available in the buffer.
PRODUCER STEPS:
1. While running:
2. Produce an item.
3. Wait until there is at least one empty slot (check empty).
4. Lock the buffer (using mutex).
5. Put the item in the buffer at the in index.
6. Move the in index to the next position (wrap around if necessary).
7. Increase the count of full items.
8. Unlock the buffer (release mutex).
9. Signal that there is a new full item (increase full).
CONSUMER STEPS:
2. While running:
3. Wait until there is at least one item to consume (check full).
4. Lock the buffer (using mutex).
5. Take an item from the buffer at the out index.
6. Move the out index to the next position (wrap around if necessary).
7. Decrease the count of full items.
8. Unlock the buffer (release mutex).
9. Signal that there is a new empty slot (increase empty)
CODE IMPLEMENTATION
OUTPUT
CODE EXPLANATION
The code includes necessary libraries for input/output operations, thread management,
semaphore operations, and utility functions.
GLOBAL VARIABLES:
The program defines a shared buffer (buffer) along with indices (in and out) that help
track the positions where the producer can add items and the consumer can remove items.
buffer_size allows users to define the maximum capacity of the buffer (up to 100), while
MAX_BUFFER_SIZE is a constant to enforce this limit.
SYNCHRONIZATION PRIMITIVES:
Two semaphores (empty and full) are initialized to keep track of the available empty slots
and filled slots in the buffer.
A mutex (buffer_mutex) is used to prevent simultaneous access to the buffer, ensuring
thread safety when accessing shared data.
PRODUCER FUNCTION
The producer generates random items and attempts to place them into the buffer. The
following steps occur:
It checks if there is space available in the buffer using the empty semaphore.
It locks the mutex to gain exclusive access to the buffer.
The producer adds the item to the buffer at the current in index and updates this index
circularly.
After adding an item, the mutex is unlocked, and the full semaphore is incremented to
indicate that there is now one more item available for consumption.
The producer sleeps for a short duration to simulate time taken for production.
CONSUMER FUNCTION
The consumer removes items from the buffer and consumes them. The process is similar to the
producer but in reverse:
It checks if there are items available using the full semaphore.
It locks the mutex to access the buffer.
The consumer retrieves an item from the buffer at the current out index, then updates this
index circularly.
The mutex is unlocked, and the empty semaphore is incremented to indicate that there is now
one more empty slot available in the buffer.
The consumer also sleeps for a short duration to simulate time taken for consumption.
MAIN FUNCTION
ANALYSIS
In my analysis , the code does a solid job of managing shared memory between the producer
and consumer threads.
The buffer acts as the central shared resource, and both threads need access to it to exchange
data.
By using semaphores (empty and full), the code effectively manages the number of available
and used slots in the buffer, ensuring neither the producer overflows it nor the consumer tries
to consume from an empty buffer.The mutex (buffer_mutex) adds another layer of safety by
ensuring that only one thread can modify the buffer at any given time.
This prevents data corruption or race conditions, which would otherwise occur if both threads
accessed the buffer simultaneously.
This shared memory model is essential in multithreaded programs where multiple threads
need to communicate or share data efficiently without conflicts.
MESSAGE PASSING
Although the shared memory model is useful for process communication, it is not always
suitable and achievable. For instance, in a distributed computing environment, the processes
exchanging data might reside in different computer systems. Thus, it is not straightforward to
establish a shared memory region for communication.
The message passing mechanism provides an alternative means processes for communication. In
this mode, processes interact with each other through messages with assistance from the
underlying operating system:
1. SENDER
1. ROLE:
The sender is responsible for creating and sending messages to another process (the receiver).
2. OPERATIONS:
Message Creation:
The sender generates a message containing the necessary data or information.
Sending the Message:
Uses a communication function or API to send the message to the intended receiver.
.
2. RECEIVER
1. ROLE:
o The receiver is responsible for accepting and processing messages sent by the sender.
2. OPERATIONS:
Waiting for Messages: The receiver continuously checks the message queue for
incoming messages.
SENDER STEPS:
3. While running:
4. Create a message to send (e.g., "Hello, Receiver!").
5. Check if the message queue has space (if it can accept new messages).
6. If there is space:
7. Send the message to the message queue.
8. Optionally, print or log that the message has been sent.
9. If the queue is full, wait or retry sending later (to avoid overflow).
RECEIVER STEPS:
1. While running:
2. Check if there are any messages in the message queue.
3. If there is a message:
4. If there are no messages, wait or check again later (to avoid busy waiting
CODE IMPLEMENTATION
OUTPUT
EXPLANATION
Pipe Creation: A pipe is created using pipe(), providing two file descriptors: one for reading
and one for writing.
Forking: The program creates a new child process using fork(). Both processes share the
same pipe.
The child process becomes the receiver.
The parent process becomes the sender.
Sender (Parent):
The child reads the message from the pipe’s read end.
It prints the message it received from the parent.
Closing Pipe Ends:
ANALYSIS
The sender-receiver message-passing mode, serves as a foundational building block for
understanding inter-process communication.
Its clarity, modularity, and interactive elements enhance its educational value while also
showcasing its applicability in practical scenarios.
Despite some limitations, the model effectively demonstrates core IPC principles and
provides a solid framework for developing concurrent applications.