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.错误代码,可能出现的错误:
示例演示:
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);
}
运行结果: