进程间通信——共享内存

发布时间:2020-07-07 15:14:32 作者:LHSTS
来源:网络 阅读:501

共享内存


进程间通信的本质是让不同的进程访问一块公共的资源。

1、共享内存是进程间通信最快的方式(为什么)

2、共享内存不提供任何的同步与互斥关系。(由用户维护,可以用信号量)

以下图解释了问题1,原因是,由于共享内存的机制,两个进程不需要拷贝拷贝数据,这个特点可能在数据较少的情况下看不出来,但是数据较多时,优势较为明显。

下图是shmat之前之后的共享内存示意图:(shmget获得共享内存后需要挂接)

进程间通信——共享内存

进程间通信——共享内存


函数:

用于Linux进程通信共享内存。共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。

shmat(把共享内存区对象映射到调用进程的地址空间)

void *shmat(int shmid, const void *shmaddr, int shmflg)

参数:

shmid共享内存标识符
shmaddr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg如果设置为SHM_RDONLY是只读模式,其他为读写模式

返回值:成功返回附加好的共享内存地址

shmdt(断开共享内存连接)

int shmdt(const void *shmaddr)

参数

shmaddr:连接的共享内存的起始地址

返回值:成功返回0

shmget(得到一个共享内存标识符或创建一个共享内存对象)

int shmget(key_t key, size_t size, int shmflg)

参数

key大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值
size大于0的整数:新建的共享内存大小,以字节为单位
flags有IPC_CREAT和IPC_EXCL(用法同前面写的一致)

返回值:成功返回共享内存标示符

注:system V分配内存的方法以页为基本单位,一般以页的整数倍分配。

shmctl完成对共享内存的控制

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

参数:


shmid

共享内存标识符

cmdIPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
buf
共享内存管理结构体。具体说明参见共享内存内核结构定义部分

共享内存实现通信的例子

comm.h

#pragma once
#include<errno.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#define _PATH_NAME_ "/temp"
#define _PROJ_ID_ 0x6666

int create_shm(int size);
int get_shm();
int destory_shm(int shm_id);
void* shm_at(int shm_id);
int shm_dt(void*shmaddr);

comm.c

#include"comm.h"

static int comm_create_shm(int size,int flags)
{
    key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
    if(_key<0)
    {
        perror("ftok");
        return -1;
    }
//    int shm_id=shmget(_key,size,IPC_CREAT | IPC_EXCL);

    int shm_id=shmget(_key,size,flags);
    if(shm_id < 0)
    {
        perror("shmget");
        return -2;
    }
    return shm_id;
}

int create_shm(int size)
{
    int flags = IPC_CREAT | IPC_EXCL|0666;
    return  comm_create_shm(size,flags);
}
int get_shm()
{
    
    int flags = IPC_CREAT;
    return  comm_create_shm(0,flags);
}
int destory_shm(int shm_id)
{
    if(shmctl(shm_id,IPC_RMID,NULL)<0)
    {    
        perror("shmctl");
        return -1;
    }
    return 0;
}

void* shm_at(int shm_id)
{
    return shmat(shm_id,NULL,0);
}
int shm_dt(void* shmaddr)
{
    return shmdt(shmaddr);
}

server.c

#include"comm.c"

int main()
{
    int shm_id = create_shm(4096);
    sleep(5);
    char* buf = (char*)shm_at(shm_id);
    sleep(1);
    sleep(1);
    while(1)
    {
        printf("%s\n",buf);
        sleep(1);
        if(strcmp(buf,"AAAAA") == 0)
        {
            break;
        }
    }
    shm_dt(buf);
    sleep(5);
    destory_sem(sem_id);
    return 0;
}

client.c

#include"comm.c"

int main()
{
    int shm_id = get_shm();
    char* buf = (char*)shm_at(shm_id);
    int index = 0;
    while(1)
    {
        buf[index++]='A';
        buf[index]='\0';
        sleep(1);
        if(index>5)
        {
            break;
        }
    }
    sleep(5);
    shm_dt(buf);
    sleep(5);
    return 0;
}








推荐阅读:
  1. system v 共享内存区
  2. Posix共享内存

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

内存 共享

上一篇:使用linux的swapoff命令关闭系统交换区

下一篇:在哪里看Mysql建的表

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》