Interprocess Communication Using System V Shared Memory and Semaphores in C
Two coordinated processes demonstrate synchronization through shared memory and semaphores. The initial process creates resources and enters a wait state. A secondary process attempts access but blocks until signaled. External intervention resumes the first process which then releasse the semaphore.
Implementation
Resource Initialization Process
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
static void handle_alarm(int sig) {
printf("Signal received: %s\n", strsignal(sig));
}
static void display_segment_info(int mem_id) {
struct shmid_ds descriptor;
if (shmctl(mem_id, IPC_STAT, &descriptor) == -1) {
perror("Status check failed");
return;
}
printf("Owner PID: %d\nSize: %zu\nAttached: %ld\n",
descriptor.shm_cpid, descriptor.shm_segsz, descriptor.shm_nattch);
}
static void modify_semaphore(int sem_id, int operation) {
struct sembuf buffer = {0, operation, SEM_UNDO};
printf("%d: Semaphore op %d start\n", getpid(), operation);
if (semop(sem_id, &buffer, 1) == -1) perror("Operation failed");
printf("%d: Semaphore op %d complete\n", getpid(), operation);
}
static void prepare_memory(void* address) {
snprintf((char*)address, 1024, "%d: Status inquiry\n", getpid());
pause();
}
int main() {
signal(SIGALRM, handle_alarm);
int mem_id = shmget(1234, 1024, IPC_CREAT | 0666);
if (mem_id == -1) { perror("Memory creation failed"); exit(1); }
printf("%d: Memory segment %d created\n", getpid(), mem_id);
void* addr = shmat(mem_id, NULL, 0);
if (addr == (void*)-1) { perror("Attachment failed"); exit(1); }
printf("%d: Memory attached at %p\n", getpid(), addr);
display_segment_info(mem_id);
int sem_id = semget(1234, 1, IPC_CREAT | 0666);
if (sem_id == -1) { perror("Semaphore creation failed"); exit(1); }
printf("%d: Semaphore set %d created\n", getpid(), sem_id);
semctl(sem_id, 0, SETVAL, 1);
modify_semaphore(sem_id, -1);
prepare_memory(addr);
modify_semaphore(sem_id, 1);
shmdt(addr);
printf("%d: Memory detached\n", getpid());
return 0;
}
Secondary Access Process
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
static void display_segment_info(int mem_id) {
struct shmid_ds descriptor;
if (shmctl(mem_id, IPC_STAT, &descriptor) == -1) {
perror("Status check failed");
return;
}
printf("Owner PID: %d\nSize: %zu\nAttached: %ld\n",
descriptor.shm_cpid, descriptor.shm_segsz, descriptor.shm_nattch);
}
static void modify_semaphore(int sem_id, int operation) {
struct sembuf buffer = {0, operation, SEM_UNDO};
printf("%d: Semaphore op %d start\n", getpid(), operation);
if (semop(sem_id, &buffer, 1) == -1) perror("Operation failed");
printf("%d: Semaphore op %d complete\n", getpid(), operation);
}
static void update_memory(void* address) {
char temp[1024];
strncpy(temp, (char*)address, sizeof(temp));
snprintf((char*)address, 1024, "%s%d: Response OK\n", temp, getpid());
printf("%s", (char*)address);
}
int main() {
int mem_id = shmget(1234, 1024, 0666);
if (mem_id == -1) { perror("Memory access failed"); exit(1); }
printf("%d: Memory segment %d accessed\n", getpid(), mem_id);
void* addr = shmat(mem_id, NULL, 0);
if (addr == (void*)-1) { perror("Attachment failed"); exit(1); }
printf("%d: Memory attached at %p\n", getpid(), addr);
display_segment_info(mem_id);
int sem_id = semget(1234, 1, 0666);
if (sem_id == -1) { perror("Semaphore access failed"); exit(1); }
printf("%d: Semaphore set %d accessed\n", getpid(), sem_id);
modify_semaphore(sem_id, -1);
update_memory(addr);
modify_semaphore(sem_id, 1);
shmdt(addr);
shmctl(mem_id, IPC_RMID, NULL);
semctl(sem_id, 0, IPC_RMID);
printf("%d: Resources cleaned up\n", getpid());
return 0;
}
Execution Sequence
- Launch first program - creates shared memory and semaphore, locks semaphore, writes initial message
- Run second program in separate terminal - blocks when attempting semaphore acuqisition
- Send SIGALRM to first process using
kill -ALRM <PID> - First process resumes, unlocks semaphore
- Second process continues, updates memory, cleans resources
- Verify cleanup with
ipcscommand