Practical 6
Aim: Developing Applications using Inter Process communication (using shared memory
and pipes)
a. IPC using Shared Memory
Shared memory allows multiple processes to access the same region of memory. This is one
of the fastest methods of IPC, as it eliminates the need for copying data between processes.
Program Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#define SHM_SIZE 1024 // Size of shared memory
// Shared memory structure
struct shared_data {
int num1;
int num2;
int sum;
};
int main() {
int shm_id;
struct shared_data *shm_ptr;
// Create a shared memory segment
shm_id = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);
if (shm_id == -1) {
perror("shmget failed");
exit(1);
// Attach the shared memory to the process
shm_ptr = (struct shared_data *)shmat(shm_id, NULL, 0);
if (shm_ptr == (void *)-1) {
perror("shmat failed");
exit(1);
// Process 1: Writing data to shared memory
shm_ptr->num1 = 10;
shm_ptr->num2 = 20;
printf("Process 1: Written num1=%d, num2=%d\n", shm_ptr->num1, shm_ptr->num2);
// Detach from shared memory
shmdt(shm_ptr);
// Fork to create Process 2
if (fork() == 0) {
// Process 2: Reading data from shared memory
shm_ptr = (struct shared_data *)shmat(shm_id, NULL, 0);
if (shm_ptr == (void *)-1) {
perror("shmat failed");
exit(1);
shm_ptr->sum = shm_ptr->num1 + shm_ptr->num2;
printf("Process 2: Read num1=%d, num2=%d, Calculated sum=%d\n", shm_ptr->num1,
shm_ptr->num2, shm_ptr->sum);
// Detach and remove shared memory
shmdt(shm_ptr);
shmctl(shm_id, IPC_RMID, NULL);
return 0;
b. IPC using Pipes
Pipes allow data to flow between processes in a unidirectional manner. One process writes to
the pipe, and the other process reads from it. Pipes can be used for communication between
related processes, typically between a parent and a child process.
Program Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pipe_fd[2]; // File descriptors for the pipe
pid_t child_pid;
char message[] = "Hello from parent to child!";
char buffer[100];
// Create a pipe
if (pipe(pipe_fd) == -1) {
perror("pipe failed");
exit(1);
// Fork to create a child process
if ((child_pid = fork()) == -1) {
perror("fork failed");
exit(1);
if (child_pid == 0) {
// Child process: reading from pipe
close(pipe_fd[1]); // Close unused write end
read(pipe_fd[0], buffer, sizeof(buffer));
printf("Child Process: Received message - %s\n", buffer);
close(pipe_fd[0]); // Close read end after use
} else {
// Parent process: writing to pipe
close(pipe_fd[0]); // Close unused read end
write(pipe_fd[1], message, sizeof(message));
printf("Parent Process: Sent message - %s\n", message);
close(pipe_fd[1]); // Close write end after use
}
return 0;
}
Practical 7
Aim: Simulate the Producer-Consumer problem using semaphores (using UNIX system
calls).
Program Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define MAX_ITEMS 5
#define BUFFER_SIZE 5
// Shared buffer
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
// Semaphores for synchronization
sem_t empty, full, mutex;
// Function for the producer
void* producer(void* param) {
int item;
while (1) {
// Produce an item (random number)
item = rand() % 100;
// Wait for an empty slot in the buffer
sem_wait(&empty);
// Wait for mutual exclusion before inserting the item
sem_wait(&mutex);
// Insert the item into the buffer
buffer[in] = item;
printf("Produced: %d at buffer[%d]\n", item, in);
in = (in + 1) % BUFFER_SIZE;
// Signal that the buffer has one more full slot
sem_post(&mutex);
sem_post(&full);
// Sleep to simulate work done by the producer
sleep(1);
// Function for the consumer
void* consumer(void* param) {
int item;
while (1) {
// Wait for a full slot in the buffer
sem_wait(&full);
// Wait for mutual exclusion before removing the item
sem_wait(&mutex);
// Remove the item from the buffer
item = buffer[out];
printf("Consumed: %d from buffer[%d]\n", item, out);
out = (out + 1) % BUFFER_SIZE;
// Signal that the buffer has one more empty slot
sem_post(&mutex);
sem_post(&empty);
// Sleep to simulate work done by the consumer
sleep(1);
int main() {
pthread_t producer_thread, consumer_thread;
// Initialize semaphores
sem_init(&empty, 0, BUFFER_SIZE); // Empty slots in the buffer
sem_init(&full, 0, 0); // Full slots in the buffer
sem_init(&mutex, 0, 1); // Mutex for mutual exclusion
// Create the producer and consumer threads
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
// Wait for the threads to finish (although they run forever in this example)
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
// Cleanup semaphores (not reached due to infinite loop)
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
return 0;