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

共享内存:
共享内存区是最快的IPC形式,一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程之间的数据交互不再通过内核了。
共享内存示意图:
这里写图片描述

我们了解了共享内存的示意图,我们再看一下它的代码是怎么样实现的:

struct shmid_ds {
        struct ipc_perm         shm_perm;       /* operation perms (与消息队列一样)*/
        int                     shm_segsz;      /* size of segment (bytes) */
        __kernel_time_t         shm_atime;      /* last attach time */
        __kernel_time_t         shm_dtime;      /* last detach time */
        __kernel_time_t         shm_ctime;      /* last change time */
        __kernel_ipc_pid_t      shm_cpid;       /* pid of creator */
        __kernel_ipc_pid_t      shm_lpid;       /* pid of last operator */
        unsigned short          shm_nattch;     /* no. of current attaches */
        unsigned short          shm_unused;     /* compatibility */
        void                    *shm_unused2;   /* ditto - used by DIPC */
        void                    *shm_unused3;   /* unused */
};

我们看到结构体的第一个成员还是一个结构体,对比消息队列,都是同一个结构体,可以想到,共享内存也是靠这个结构体进行连接与区别的。

创建和打开共享内存:   key--> key_t ftok(const char* pathname,int id)

int shmget(key_t key,  //共享内存段名字
            size_t size,//想分配多大字节段 ,系统会选择4K的倍数
                int shmflg);//IPC_CREAT|0644  0

将共享内存挂载到自己的虚拟地址空间:
void *shmat(int shmid,  //id
            const void *shmaddr, // NULL 
                int shmflg); // 0

返回值:返回挂载在虚拟地址空间的起始地址

卸载共享内存段:
int shmdt(const void *shmaddr );//参数是shmat返回的地址

删除共享内存:
ipcrm -M key
int shmctl(id, IPC_RMID,0);

下面是两个进程使用共享内存实现通信:
server.c

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

int main()
{
    key_t key = ftok(".",0x6666);  //ipc 键值对
    if(key < 0)
    {
        perror("ftok \n");
        return -1;
    }
    int shmid = 0;
    //创建共享内存
    shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);
    if(shmid < 0)
    {
        perror("shmget \n");
        return -2;
    }
    char *addr = shmat(shmid,NULL,0);
    sleep(2);

    int i = 0;
    while(i < 26)
    {
        printf("client# %s\n",addr);
        sleep(1);
        i++;
    }
    shmdt(addr);
    sleep(2);
    //卸载共享内存
    int tmp = 0;
    tmp = shmctl(shmid,IPC_RMID,NULL);
    if(tmp < 0)
    {
        perror("shmctl \n");
        return -1;
    }
    return 0;
}

client.c

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

int main()
{
    key_t key = ftok(".",0x6666);
    if(key < 0)
    {
        perror("ftok \n");
        return -1;
    }
    //获取共享内存
    int shmid = shmget(key,4096,IPC_CREAT);
    if(shmid < 0)
    {
        perror("shmget \n");
        return -1;
    }
    //挂载内存
    char *addr = shmat(shmid,NULL,0);
    sleep(2);

    //往共享内存中写东西
    int i = 0;
    while(i < 26)
    {
        addr[i] = 'A' + i;
        i++;

        addr[i] = 0;
        sleep(1);
    }
    //卸载共享内存
    int tmp = 0;
    tmp = shmdt(addr);
    if(tmp < 0)
    {
        perror("shmctl \n");
        return -1;
    }
    sleep(1);
    return 0;
}

效果图:
这里写图片描述

我们可以通过 ipcs -m 查看系统中有多多少个共享内存:
这里写图片描述

在程序运行中,再看共享内存
这里写图片描述

由于共享内存的生命周期随着系统,我们可以在程序中用 shmctl 函数 删除共享内存,
也可以用 ipcrm -m + shmid 指令来删除。

上面就是我对共享内存的总结,希望对在学习的小伙伴有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值