进程间的通信——共享内存

进程间的通信——消息队列https://blog.csdn.net/q496958148/article/details/79951727
进程间的通信——信号量https://blog.csdn.net/q496958148/article/details/79977093
进程间的通信——管 道https://blog.csdn.net/q496958148/article/etails/79948367

概述:

共享内存是最快的IPC形式。因为只要建立这样一个环境的话,进程间的通信就需要内核的传递了,只要俩进程看到同一块地址空间,只要任何一个做出修改,其他的都可以看到。而相对应的管道、消息队列都是你写进去然后内核进行解析成二进制。然后转移到接收端,又得将二进制解析成正常的信息。这样就会大大降低效率。

共享内存示意图:
这里写图片描述

共享内存的数据结构:

 struct shmid_ds {
                struct ipc_perm shm_perm;        /* operation perms */
                int     shm_segsz;               /* size of segment (bytes) */
                time_t  shm_atime;               /* last attach time */
                time_t  shm_dtime;               /* last detach time */
                time_t  shm_ctime;               /* last change time */
                unsigned short  shm_cpid;        /* pid of creator */
                unsigned short  shm_lpid;        /* pid of last operator */
                short   shm_nattch;              /* no. of current attaches */

                                                 /* the following are private */

                unsigned short   shm_npages;     /* size of segment (pages) */
                unsigned long   *shm_pages;      /* array of ptrs to frames -> SHMMAX */ 
                struct vm_area_struct *attaches; /* descriptors for attaches */
        };
  • 创建共享内存
       int shmget(key_t key, size_t size, int shmflg);
       //key 这个内存段的名字(暗号和消息队列一样)
       //size 共享内存的大小
       //shmflg IPC_CREAT:创建新的共享内存。 IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消共享内存已经存在,则返回错误。 IPC_NOWAIT:读写共享内存要求无法满足时,不阻塞。
  • 将共享内存连接到进程的地址空间(上面的那个图)
       void *shmat(int shmid, const void *shmaddr, int shmflg);
    //shmid 共享内存标识
    //shmaddr 指定连接的地址
    //shmflg SHM_RND 和 SHM_RDONLY 俩个取值
    //返回值成功为指向共享内存的指针,失败为-1
  • 将共享内存与当前进程脱离
        int shmdt(const void *shmaddr);
    //shmaddr 由shmat返回的指向共享内存的地址
    //返回值成功为0,失败为-1
    //切记 只是将共享内存和进程的连接脱离,并不是将共享内存删除(只是取消了它们之间的映射关系)
  • 控制共享内存
        int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    //shmid 共享内存标示符
    //cmd 将要采取的动作IPC_STAT将传进来的参数设置为共享内存的关联值 IPC_SET在有权限的前提下,将共享内存的关联值跟换为传进来参数的值 IPC_RMID删除共享内存
    //buf 指向一个保存着共享内存的模式状态和访问权限的数据结构
    //返回值成功为0,失败为-1 

实例:
要求功能:进程A每隔一秒往共享内存写一个数据,进程B也是每隔一秒打印出当前共享内存的数据,并且要求在30秒之内自动退出,删除共享内存。

shm.h:

#pragma once

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

#define TAPH "."
#define NUM 0x6666

int createShm(int size);

int getShm(int size);

int destroyShm(int shmid);

shm.c:

#include "shm.h"

int createShm(int size)
{
    key_t key = ftok(TAPH,NUM);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    int shmid = shmget(key,size,IPC_CREAT|IPC_EXCL|0666);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    return shmid;
}

int getShm(int size)
{
    key_t key = ftok(TAPH,NUM);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    int shmid = shmget(key,size,IPC_CREAT);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    return shmid;
}

int destroyShm(int shmid)
{
    int i = shmctl(shmid,IPC_RMID,NULL);
    if(i < 0)
    {
        perror("shmctl");
        return -1;
    }
    return 0;
}

server.c:

#include "shm.h"

int main()
{
    int shmid = createShm(1024);

    void *pshm = shmat(shmid,NULL,0);
    int i = 0;
    while(i < 30)
    {
        printf("--:%s\n",pshm);
        i++;
        sleep(1);
    }
    shmdt(pshm);
    destroyShm(shmid);
    return 0;
}

client.c:

#include "shm.h"

int main()
{
    int shmid = getShm(1024);
    sleep(1);
    char *pshm = shmat(shmid,NULL,0);
    int i = 0;
    int j = 0;
    while(i < 30)
    {
        pshm[i] = 'a' + i;
        i++;
        pshm[i] = 0;
        if(i >14)
        {
            pshm[i-2*j] = '\0';
            j++;
        }
        sleep(1);
    }
    shmdt(pshm);
    sleep(1);
    return 0;
}

Makefile:

.PHONY:all
all:client server


client:client.c shm.c
    gcc $^ -o $@;
server:server.c shm.c
    gcc $^ -o $@;

.PHONY:clean
clean:
    rm -f client server

效果图:
这里写图片描述

共享内存中如果出现一下情况:
这里写图片描述
这里写图片描述

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页