Linux interprocess communication---shared memory

  • Shared memory allows multiple processes to share a given memory space, and processes can directly read and write memory, so it is the fastest in IPC.
  • In Linux, the kernel specially sets aside a memory area as a shared memory area for multiple processes to exchange information. The process that needs to communicate maps the shared memory area to its own private address space, so that reading and writing the process address space is equivalent to reading and writing the memory area. The header file that uses shared memory is #include <sys/shm.h>
  • Since multiple processes read and write the same memory area, synchronization processing is required, which is generally used in conjunction with semaphores (mutexes and record locks can also be used).
  • Shared memory segment is 32M bytes by default.
  • The operation flow of shared memory (only used for related processes, that is, communication between related processes):
    • Create/open a shared memory area
    • Map the specified shared memory into the address space of the process
    • Unmapping shared memory
    • Delete shared memory object (IPC object represented by key)
  • Common functions of shared memory:
    • shmget(key, size, flag): Create a new shared memory segment or obtain an existing shared memory segment, the function returns the ID (shmid) of the shared memory segment. The key identifies the key value of the shared memory. When two processes use the same key, the shmid obtained by shmget is the same, and the same shared memory can be accessed at this time. size indicates the obtained shared memory size. The flag indicates the access permission of the shared memory block. If you want to create a new shared memory segment when it does not exist, use IPC_CREAT and the permission value to do the bitwise AND operation.
    • shmat(shmid, addr, flag): Map the shared memory segment to the address space of the process. The addr should be set to 0, and the address is chosen by the system (the address is between the stacks). flag is a set of flag bits, usually 0. On a successful call, returns a pointer to the first byte of shared memory.
    • shmdt(addr): Separates the process address space from the shared memory segment, making the shared memory unavailable to the current process.
    • shmctl(shm_id, command, buf): Control shared memory. Command parameters: IPC_RMID (delete shared memory segment), IPC_STAT and IPC_SET (not commonly used)
  • How unrelated processes (non-related processes) share memory:
    • Using XSI Shared Storage Functions
    • Use mmap to map the same file into the address space of multiple processes, using the MAP_SHARED flag to ensure that one process writes to the storage segment and the other process sees it.
  • Advantages and disadvantages of using shared memory:
    • Advantages: convenient and simple interface; data does not need to be transmitted, but directly reads and writes memory, which is highly efficient; there is no restriction on communication between related processes such as anonymous pipes, which is suitable for communication between unrelated processes.
    • Disadvantage: need to rely on external synchronization mechanism
  • An example of the use of shared memory, create two processes, shmwrite writes data to shared memory, and shmread reads data from shared memory:
    • The shmread process creates a shared memory segment, maps the shared memory segment to its own memory space, and reads data from the memory.
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <sys/shm.h>
struct shared_use_st  
{  
    int wirte_read_flag;         // As a flag, non-0: means readable, 0 means writable   
    char text[ 1024 ];               // Record the text written and read   
};
 int main()  
{  
    int running = 1 ;     // The flag of whether the program continues to run   
    void *shm = NULL;     // Original first address of the allocated shared memory   
    struct shared_use_st *shared;    // Pointing to shm   
    int shmid;          // Shared memory ID number  
     // Create shared memory, when the key is the same, the returned shmid is the same, then the two processes use the same shared memory, IPC_CREAT means to create a shared memory block with the specified key 
    shmid = shmget((key_t) 1234 , sizeof ( struct shared_use_st), 0666 | IPC_CREAT);  
     if (shmid == - 1 )  
    {  
        fprintf(stderr, "shmget failed\n");  
        exit(EXIT_FAILURE);  
    }  
    // Connect shared memory to the address space of the current process   
    shm = shmat(shmid, 0 , 0 );  
     if (shm == ( void *)- 1 )  
    {  
        fprintf(stderr, "shmat failed\n");  
        exit(EXIT_FAILURE);  
    }  
    printf( " \nMemory attached at %X\n " , ( int )shm);  
     // Set shared memory   
    shared = ( struct shared_use_st* )shm;  
    shared ->wirte_read_flag = 0 ;   // Set as writable 
    while (running)    // Read data in shared memory   
    {  
         // Readable mode, reading from the address space shm of the process is equivalent to reading 
        if from shared memory (shared->wirte_read_flag != 0 )  
        {  
            printf("Receive Message: %s", shared->text);  
            sleep(rand() % 3 );  
             // After reading the data, set wirte_read_flag to make the shared memory segment writable   
            shared->wirte_read_flag = 0 ;  
             // Enter end, exit the loop   
            if (strncmp(shared->text, " end " , 3 ) == 0 )  
                running = 0;  
        }  
        else         // There are other processes writing data and cannot read data   
            sleep( 1 );  
    }  
    // Separate shared memory from the current process   
    if (shmdt(shm) == - 1 )  
    {  
        fprintf(stderr, "shmdt failed\n");  
        exit(EXIT_FAILURE);  
    }  
    // delete shared memory   
    if (shmctl(shmid, IPC_RMID, 0 ) == - 1 )  
    {  
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");  
        exit(EXIT_FAILURE);  
    }  
    exit(EXIT_SUCCESS);  
}  
    • The shmwrite process obtains the shared memory, maps the shared memory to its own memory space, and writes data to the memory.
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <sys/shm.h>  
struct shared_use_st  
{  
    int wirte_read_flag;         // As a flag, non-0: means readable, 0 means writable   
    char text[ 1024 ];               // Record the text written and read   
};
 int main()  
{  
    int running = 1 ;  
     void *shm = NULL;  
     struct shared_use_st *shared = NULL;  
     char buffer[ 1024 + 1 ];   // used to save the input text   
    int shmid;  
     // create shared memory, when the key is the same, the returned The same is true for shmid, then two processes access the same shared memory, IPC_CREAT means to create a shared memory with a specified key 
    shmid = shmget((key_t) 1234 , sizeof ( struct shared_use_st), 0666 | IPC_CREAT);  
     if (shmid == - 1 )  
    {  
        fprintf(stderr, "shmget failed\n");  
        exit(EXIT_FAILURE);  
    }  
    // Connect shared memory to the address space of the current process   
    shm = shmat(shmid, ( void *) 0 , 0 );  
     if (shm == ( void *)- 1 )  
    {  
        fprintf(stderr, "shmat failed\n");  
        exit(EXIT_FAILURE);  
    }  
    printf( " Memory attached at %X\n " , ( int )shm);  
     // Set shared memory   
    shared = ( struct shared_use_st* )shm;  
     while (running)     // Write data to shared memory   
    {  
         // Data not yet If it is read, wait for the data to be read, and cannot write to the shared memory 
        while (shared->wirte_read_flag == 1 )  
        {  
            sleep(1);  
            printf("Waiting...\n");  
        }  
        // Writing data to shared memory, writing to the address space shm of the process is equivalent to writing to shared memory!  
        printf( " Enter some text: " );  
        fgets(buffer, BUFSIZ, stdin);  
        strncpy(shared ->text, buffer, 1024 );  
         // After writing the data, set written to make the shared memory segment readable   
        shared->wirte_read_flag = 1 ;  
         // Enter end, exit the loop   
        if (strncmp(buffer, " end " , 3 ) == 0 )  
            running = 0;  
    }  
    // Separate shared memory from the current process   
    if (shmdt(shm) == - 1 )  
    {  
        fprintf(stderr, "shmdt failed\n");  
        exit(EXIT_FAILURE);  
    }  
    sleep(2);  
    exit(EXIT_SUCCESS);  
}  

(ps: The above program is transferred from http://blog.csdn.net/ljianhui/article/details/10253345 )

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324522642&siteId=291194637