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

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

共享内存:
1.共享内存是最为高效的进程间通信方式
2.共享内存往往需要同步与互斥的机制(信号灯集)
3.ipc 对象不会随进程的结束而销毁,可以多次利用。必须手动注销或者系统重新启动才会销毁。

/usr/include/linux 中shm.h里对共享内存的大小,数量进行了规定,以及属性信息。
ipcs -m 查看共享内存
ipcs -q 查看消息队列
ipcs -s 查看信号量集
ipcrm -m id 删除一个ipc对象
-s
-q

key_t ftok(const char *pathname, int proj_id);
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
功能:获取一个key值
参数:pathname 文件
proj_id 大于0 整数
返回值:key -1

int shmget(key_t key, size_t size, int shmflg);
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
功能:创建或者打开一个共享内存
参数:key:用来唯一识别一个ipc对象
size:要申请的共享内存的大小,以字节为单位
shmflg:打开一个共享内存的权限
IPC_CREAT:创建一个ipc对象
IPC_EXCL:如果这个对象已经存在则返回errno=EEXIST
mode:创建权限(0666/0766)
返回值:共享内存表示符 -1

void *shmat(int shmid, const void *shmaddr, int shmflg);
头文件:
#include <sys/types.h>
#include <sys/shm.h>
功能 : 映射一个共享内存
参数 :shmid : 共享内存标识符
shmaddr : 指定映射共享内存的首地址 (可以用malloc 申请空间)
NULL表示系统自动分配地址
shmflg : 共享内存的使用权限 SHM_RDONLY 表示只读
0 表示可读可写
返回值 : 返回映射共享内存首地址
返回错误码

int shmdt(const void *shmaddr);
头文件:
#include <sys/types.h>
#include <sys/shm.h>
功能: 消除一个映射
(进程结束或者共享内存被销毁后,映射关系会自动断开。但是我们通常习惯在用完后用手动方式消除映射)

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
功能 : 共享内存控制
参数 : shmid
cmd 操作命令
IPC_STAT (获取对象属性)
IPC_SET (设置对象属性)
IPC_RMID (删除对象)
buf :共享内存属性
struct shmid_ds buf;
shmctl(shmid,IPC_STAT,&buf); ------> 获取共享内存属性放到buf中
shmctl(shmid,IPC_SET,&buf); ------> 将共享内存属性设置为buf内容
shmctl(shmid,IPC_RMID,NULL);------》删除共享内存
返回值 0 -1

共享内存创建和使用顺序:
设置key值 ------》创建或者打开共享内存-----》映射共享内存 -----》使用共享内存 -----》解除映射 -----》删除共享内存

下面来看看两个demon程序,read和write:

//sharewrite.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1   //在开发中,可以考虑定义成宏的形式来表示某些返回状态,或者是使用枚举的形式
#define success 0
int main(void){
    key_t keyVal;
    int shmid;
    char *shm=NULL;
    keyVal=ftok(".",'a');  //创建一个key值
    if(ERROR==keyVal){
        printf("ftok key create fail\n");
        return ERROR;
    }else{
        printf("key:%d\n",keyVal);
    }

    shmid=shmget(keyVal,128, IPC_CREAT|0666);  //获取共享内存的表示ID
    if(ERROR==shmid){
        printf("shmget fail\n");
        return ERROR;
    }else{
        printf("shmget success\n");
    }
    shm=(char *)shmat(shmid,0,0);  //映射并获得共享内存的首地址
    if(NULL==shm){
        printf("shmat fail\n");
        return ERROR;
    }else{
        printf("shmat success\n");
    }
    char buf[256] = {0};
    while(1){
        fgets(buf,256,stdin);  //从终端获取内容
        strncpy(shm,buf,256);  //写入到共享内存中
        if(strncmp(buf,"quit",4)==0){
            break;
        }
        sleep(1);
    }

    int id=shmdt((void *)shm);  //解决共享内存的映射
    if(id==ERROR){
        printf("shmdt fail\n");
        return ERROR;
    }
    struct shmid_ds sbuf;
    int ret=shmctl(shmid, IPC_RMID, &sbuf);  //IPC_RMID:删除共享内存
    if(ERROR==ret){
        printf("shmctl fail\n");
        return ERROR;
    }

    return 0;
}
//shareread.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1
#define success 0
int main(void){
    key_t keyVal;
    int shmid;
    char *shm=NULL;

    keyVal=ftok(".",'a');  //创建一个key值
    if(ERROR==keyVal){
        printf("ftok key create fail\n");
        return ERROR;
    }else{
        printf("key:%d\n",keyVal);
    }

    shmid=shmget(keyVal,128, IPC_CREAT|0666);  //获取共享内存的表示ID
    if(ERROR==shmid){
        printf("shmget fail\n");
        return ERROR;
    }else{
        printf("shmget success\n");
    }
    shm=(char *)shmat(shmid,0,0);  //映射并获得共享内存的首地址
    if(NULL==shm){
        printf("shmat fail\n");
        return ERROR;
    }else{
        printf("shmat success\n");
    }
    char buf[256] = {0};
    while(1){
        if(shm[0]!='\0'){    //如果共享内存的第一个位置不是‘\0’,表示有内容写入了
            printf("%s\n",shm);
        }
        if(strncmp(shm,"quit",4)==0){
            break;
        }
        memset(shm,0,128);  //每次需要清空一下内存中的内容
        sleep(1);
    }

    int id=shmdt((void *)shm);  //解决共享内存的映射
    if(id==ERROR){
        printf("shmdt fail\n");
        return ERROR;
    }
    struct shmid_ds sbuf;
    int ret=shmctl(shmid, IPC_RMID, &sbuf);  //IPC_RMID:删除共享内存
    if(ERROR==ret){
        printf("shmctl fail\n");
        return ERROR;
    }

    return 0;
}

在这里插入图片描述
在开始运行之前,先看一是否有已经创建好的共享内存
在这里插入图片描述通过图片中看到,目前没有刚刚创建好的共享内存,那就先运行shareread,看看结果
在这里插入图片描述
在这里插入图片描述发现已经创建好一个属于aaron的共享内存区域,大小为128 bytes,nattch的数值为1,那接下来运行sharewrite,看看结果如何:
在这里插入图片描述
在这里插入图片描述发现nattch的数值已经变为了2,说明已经运行和创建成功现在就可以进行通信了,来看看效果吧
在这里插入图片描述接下来输入quit看看是什么样的结果:
在这里插入图片描述创建的共享内存已经消失了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值