Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Interprocess Communication Using System V Shared Memory and Semaphores in C

Tech 1

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

  1. Launch first program - creates shared memory and semaphore, locks semaphore, writes initial message
  2. Run second program in separate terminal - blocks when attempting semaphore acuqisition
  3. Send SIGALRM to first process using kill -ALRM <PID>
  4. First process resumes, unlocks semaphore
  5. Second process continues, updates memory, cleans resources
  6. Verify cleanup with ipcs command
Tags: c

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.