Implementing Shared Memory in C: IPC Mechanism

Implementing Shared Memory in C: IPC Mechanism

In operating systems, Inter-Process Communication (IPC) is a mechanism that allows different processes to exchange data. Shared memory is an important method of IPC that allows multiple processes to access the same physical memory. This method is fast and efficient, making it suitable for applications that require frequent exchange of large amounts of data.

This article will detail how to implement shared memory using C language and provide code demonstrations.

1. Basic Concepts of Shared Memory

In Linux systems, shared memory is typically managed through system calls such as <span>shmget</span>, <span>shmat</span>, <span>shmdt</span>, and <span>shmctl</span>. Here is a brief description of these functions:

  • shmget: Creates a new shared memory segment or obtains the identifier of an existing shared memory segment.
  • shmat: Attaches the specified shared memory segment to the address space of the current process.
  • shmdt: Detaches a shared memory segment associated with the current process.
  • shmctl: Controls access permissions and status, including deleting a shared memory segment.

2. Program Structure

We will write a simple example to demonstrate how a process communicates through shared memory. In this example, a parent process will create a child process, and both will communicate through a common data area.

2.1 Including Header Files

We need to include some necessary header files:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

2.2 Defining Constants and Global Variables

Define some constants for creating and accessing shared memory:

#define SHM_SIZE 1024 // Define the size of the shared value

3. Creating and Using Shared Memory

Below is the complete code example:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define SHM_SIZE 1024 // Define the size of the shared area
int main() {
    int shmid;
    key_t key = ftok("myfile",65); // Create a unique key
    char *str;
    // Create/get shared memory segment
    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("Failed to create shared memory");
        exit(1);
    }
    // Attach it to our address space
    str = (char*) shmat(shmid, NULL, 0);
    if (str == (char*)(-1)) {
        perror("Failed to attach shared memory");
        exit(1);
    }
    printf("Write Data To Shared Memory: ");
    fgets(str, SHM_SIZE, stdin); // Read string from standard input
    printf("Data written in the memory: %s\n", str);
    printf("Waiting for child process to read...\n");
    sleep(5);
    // Detach the shared memory segment associated with the current process
    if (shmdt(str) == -1) {
        perror("Failed to detach shared memory");
        exit(1);
    }
    return 0;
}

3.1 Child Program (Reader)

To allow the child program to read the data written by the parent program, we can write the following code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024
int main() {
    int shmid;
    key_t key = ftok("myfile",65);
    /* Get shared memory segment */
    shmid = shmget(key, SHM_SIZE, IPC_CREAT |0666);
    char *str;
    /* Attach it to our address space */
    str = (char*) shmat(shmid,NULL,0);
    printf("Data read from shared memory: %s\n", str);
    /* Optionally detach and delete */
    shmdt(str);
    return 0;
}

Usage Instructions

To test the above code, follow these steps:

  1. First, save the parent program (writer) and child program (reader) content as two separate C source files, such as <span>parent.c</span> and <span>child.c</span>.
  2. Then, compile them into executable files in the terminal:
gcc parent.c -o parent
gcc child.c -o child
  1. First run the parent process, then run the child process, and observe the output. You will see the data written by the parent process being read by the child process in the terminal.

Conclusion

Through the above example, we successfully demonstrated how to use the APIs provided by Linux to implement simple multithreaded connections in C language. In fact, due to its speed advantages, shared memory is particularly popular for real-time or high-performance computing tasks. However, in practical applications, attention must also be paid to data security and race condition issues, so other synchronization mechanisms, such as semaphores, are often combined to ensure data consistency and integrity. We hope this article helps you understand and apply IPC, especially in circular buffers, effectively.

Leave a Comment