IPC (four) --------- shared memory

1. Introduction to shared memory

      1. Shared memory is a part of physical memory shared by multiple processes.

      2. If all user space processes want to operate shared memory, they must map it to their own virtual memory space, and operate the shared memory through the mapped virtual memory space address, so as to achieve data communication between processes.

      3. Shared memory is the fastest way to share data between processes, an efficient IPC mechanism.

、 、 API

    1. Create shared memory

          int shmget(key_t key, size_t size , int shmflag);

          parameter:

              key: The key value of the shared memory, specified by the user.

              size: The size of the shared memory.

             shmflag: a combination of IPC_CREAT, IPC_EXCL, 0777 and other permissions

        Returns: success, returns the identification ID of the shared memory in the kernel, failure, returns -1.

  2. Shared memory control

         int shmctl ( int shmid, int cmd, struct shmid_ds *buf);

         parameter:

              shmid: shared memory ID

              cmd: 

                      IPC_STAT Get shared memory attributes

                      IPC_SET set shared memory attributes

                      IPC_RMID delete shared memory

            buf: pointer to shared memory attributes

 

          Return: Return 0 for success, -1 for error

    3. Shared memory mapping

          void * shmat( int shmid ,char * shmaddr, int shmflag);

          parameter:

               shmid: shared memory ID

              shmaddr: the address mapped to the virtual memory space of the process, generally set to 0, allocated by the system

              shmflag: If shmaddr is set to 0, shmflag is also set to 0

         Return: Return the address mapped from the shared memory to the virtual memory space on success, and -1 on failure.

         Note: The child process does not inherit the shared memory created by the parent process, it is shared by everyone, but the child process inherits the address mapped by the parent process.     

     4. Unmap shared memory

         int shmdt(char * shmaddr);

         Return: Return -1 on failure.

Three, code practice

      The parent process creates shared memory, and the parent process writes data to the shared memory. After writing, it notifies the child process, and the child process reads data from the shared memory.

      Details: 1. Before the parent process has finished writing to the shared memory, the child process is in a waiting state. At this time, the notification and blocking are temporarily simulated by the characteristics of the pipeline (replaced with a semaphore later).

                 2. The child process inherits the pipe created by the parent process, so the pipe will be destroyed after the two processes are used up

                 3. The child process only inherits the address mapped from the parent process's shared memory to the virtual memory, and the shared memory is only one segment, so it is enough for the two processes to destroy the shared memory once, but the shared memory mapping must be removed.

    Create tell.c and tell.h to synchronize the information of the two processes with the feature class of the pipeline.

    

#include <stdio.h>
#include <unistd.h>
#include "tell.h"



int fd[2];

//管道初始化
void init()
{
    if(pipe(fd) < 0)
    {
        printf("pipe create error\n");
    }

}


//利用管道进行等待
void wait_pipe()
{
    char c;



    //利用管道默认是阻塞的特性
    if(read(fd[0],&c,1) < 0)
    {
        printf("pipe read error\n");
    }
}


//利用管道进行通知
void notify_pipe()
{
    char c = 'c';

    if(write(fd[1],&c,1) < 0)
    {
        printf("pipe write error\n");
    }

}


//销毁管道
void destory_pipe()
{
    close(fd[0]);
    close(fd[1]);

}

Implement inter-process access to shared memory

#include <stdio.h>
#include "tell.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>




/*  父进程创建共享内存,父进程向共享内存中写数据,
 *子进程从共享内存中读数据.
 * */



int main(void)
{

    //父进程创建共享内存,大小1024
    int shmId = shmget(IPC_PRIVATE,1024,IPC_CREAT|IPC_EXCL|0777);
    
    if(shmId < 0)
    {
        printf("share mem create error\n");

        return -1;
    }
    
    //初始化管道
    init();

    pid_t pid = fork();

    if(pid > 0)
    {//parent process
        //将共享内存映射到父进程虚拟内存空间中
        int *p = (int *)shmat(shmId,0,0);

        if(p == (int *) (-1))
        {
            printf("parent process shmat error\n");

            return -1;
        }
        
        //向共享内存中写入数据
        *p = 100;
        *(p+1) = 200;

        //通知数据已经写好了
        notify_pipe();

        //父进程共享内存结束映射
        shmdt((char *)p);

        //父进程创建的pipe,子进程也会继承,所以父子进程都有读端和写段两个管道,
        //用完了都需要将其销毁
        destory_pipe();

        
        //等待回收子进程
        wait(0);

    
    }else if(pid == 0)
    {//child parent

        //等待共享内存写好数据
        wait_pipe();
        //子进程将共享内存映射到自己虚拟空间中
        int *p = (int *)shmat(shmId,0,0);

        if(p == (int *)-1)
        {
            printf("child process shmat error\n");

            return -1;
        }
            
        //读共享内存    
        printf("share mem contex:start:%d,end:%d\n",*p,*(p+1));

        //子进程共享内存结束映射
        shmdt((char *)p);

        //子进程也要销毁管道
        destory_pipe();


        //共享内存不需要继承,只有一份,所以,在子进程或者父进程删除一次就行
        shmctl(shmId,IPC_RMID,NULL);
    }


    return 0;
}

Test Results:

  

Guess you like

Origin blog.csdn.net/weixin_40204595/article/details/112696725