Linux编程实践----共享内存的演示(IPC)

Linux编程实践----共享内存的演示(IPC)

1.共享内存是允许两个不相关的进程访问同一个逻辑内存,其是进程之间共享数据的一种非常有效的方式;

一般使用时,是用共享内存来提供对大块内存的有效访问,用传递小消息来进行同步对该共享内存的访问!

 

2.共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。

 

函数名

头文件名

参数值意义

返回值

作用

int shmget(key_t key,size_t size,int shmflg)#include <sys/shm.h>

1.共享内存段的名字;

2.共享内存的大小;

3.IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符;IPC_CREAT|IPC_EXCL:如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错

共享内存标识符;失败返回-1.

得到一个共享内存标识符或者是创建

一个共享内存对象并返回其标识符。

void *shmat(int shm_id,const void *shm_addr,int shmflg)#include <sys/shm.h>

1.共享内存标识符;

2.指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置。(自己指定,会造成应用程序对硬件的依赖性过高,最好是内核自己决定);

3.SHM_RDONLY:为只读模式,其他为读写模式

1.成功:附加好的共享内存地址

2.出错:-1,错误原因存于error中

连接标识符为shm_id的共享内存,成功后把共享内存对象映射到调用进程的地址空间,便可以访问了。

fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地址自动脱离(detach)。进程结束后,已连接的共享内存地址会自动脱离(detach)。

int shmdt(const void * sjm_addr)#include <sys/shm.h>1.连接的共享内存的起始地址

1.成功返回0;

2.失败返回-1,原因存在于error中。

shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存。

本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程

int shmctl(int shm_id,int cmd,struct shmid_ds *buf)#include <sys/shm.h>

1.共享内存的标识符;

2.cmd:命令---IPC_STAT:把buf中的数据设置为当前共享内存的状态值;IPC_SET:把共享内存的当前状态设置为buf中给出的值,要求进程有一定的权限;IPC_RMID:删除共享内存段。

1.成功返回0;

2,失败返回-1,原因在于error中。

对共享内存的控制。

 

3.错误代码,可能出现的错误:

EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存
EFAULT:参数buf指向无效的内存地址
EIDRM:标识符为shmid的共享内存已被删除
EINVAL:无效的参数cmd或shmid
EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

 

示例演示:

1.comm.h

using namespace std;
class people
{
public:
        int who;
        int  age;

};


2.创建共享内存,消费者,不断读取生产者写入的数据!

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/shm.h>
#include<iostream>
#include<string>
using namespace std;

#include"comm.h"

int main()
{
        int running=1;
        void *share_memory=(void *)0;
        people *walker;
        int shm_id=shmget((key_t)12,sizeof(people),0666 | IPC_CREAT);
        if(shm_id<0)
        {
                cout<<"shmget failed!"<<endl;
                exit(EXIT_FAILURE);
        }
        share_memory=shmat(shm_id,(void *)0,0);
        if((long)share_memory<0)
        {
                cout<<"shmat failed"<<endl;
                exit(EXIT_FAILURE);
        }
        cout<<(long)share_memory<<endl;
        walker=(people *)share_memory;
        walker->who=0;
        int times=0;
        while(running)
        {
                if(walker->who==1)
                {
                        cout<<"I am consumer ,OutputCurrent Age:"<<walker->age<<endl;
                        sleep(3);
                        walker->who=0;
                        times++;
                        if(times==3) running=0;
                }

        }
        if(shmdt(share_memory)==-1)
        {
                cout<<"shmdt failed"<<endl;
                exit(EXIT_FAILURE);
        }
         if(shmctl(shm_id,IPC_RMID,0)==-1)
        {
                cout<<"shmctl failed"<<endl;
                exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
}


 

3.生产者,不断向共享内存中写入数据!

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/shm.h>
#include<iostream>
#include<string>
using namespace std;

#include"comm.h"

int main()
{
        int running=1;
        void *share_memory=(void *)0;
        people *walker;
        int shm_id=shmget((key_t)12,sizeof(people),0666 | IPC_CREAT);
        if(shm_id<0)
        {
                cout<<"shmget failed!"<<endl;
                exit(EXIT_FAILURE);
        }
        share_memory=shmat(shm_id,(void *)0,0);
        if((long)share_memory<0)
        {
                cout<<"shmat failed"<<endl;
                exit(EXIT_FAILURE);
        }
        cout<<(long)share_memory<<endl;
        walker=(people *)share_memory;
        walker->who=0;
        int times=0;
        while(running)
        {
                if(walker->who==1)
                {
                        cout<<"I am consumer ,OutputCurrent Age:"<<walker->age<<endl;
                        sleep(3);
                        walker->who=0;
                        times++;
                        if(times==3) running=0;
                }

        }
        if(shmdt(share_memory)==-1)
        {
                cout<<"shmdt failed"<<endl;
                exit(EXIT_FAILURE);
        }
         if(shmctl(shm_id,IPC_RMID,0)==-1)
        {
                cout<<"shmctl failed"<<endl;
                exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
}

运行结果:

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值