1.共享内存原理
共享内存允许两个或者多个进程共享给定的存储区域。 共享内存的特点 1、共享内存是进程间共享数据的一种最快的方法。一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。 2、使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。 若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。
1.1.共享内存示意图:
在ubuntu 部分版本中共享内存限制值如下 共享存储区的最小字节数:1 共享存储区的最大字节数:32M 共享存储区的最大个数:4096 每个进程最多能映射的共享存储区的个数:4096
2.共享内存的创建和使用
2.1获得一个共享存储标识符
int shmget(key_t key, size_t size,int shmflg);
功能: 创建或打开一块共享内存区。
参数: key:IPC键值。 size:该共享存储段的长度(字节)。 shmflg:标识函数的行为及共享内存的权限。
shmflg说明: PC_CREAT:如果不存在就创建 IPC_EXCL:如果已经存在则返回失败 位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式和open函数的mode_t一样,但可执行权限未使用。
返回值: 成功:返回共享内存标识符。 失败:返回 -1。
操作: 使用shell命令操作共享内存: 查看共享内存 ipcs -m 删除共享内存 ipcrm -m shmid
2.2.共享区映射
void *shmat(int shmid, const void *shmaddr,int shmflg);
功能: 将一个共享内存段映射到调用进程的数据段中。
参数: shmid:共享内存标识符。 shmaddr:共享内存映射地址(若为NULL则由系统自动指定),推荐使用NULL。 shmflg:共享内存段的访问权限和映射条件。
shmflg说明: 0:共享内存具有可读可写权限。 SHM_RND:(shmaddr非空时才有效)。 没有指定SHM_RND则此段连接到shmaddr所指定的地址上(shmaddr必需页对齐)。 指定了SHM_RND则此段连接到shmaddr- shmaddr%SHMLBA 所表示的地址上。
返回值: 成功:返回共享内存段映射地址。 失败:返回 -1。
注意: shmat函数使用的时候第二个和第三个参数一般设为NULL和0,即系统自动指定共享内存地址,并且共享内存可读可写。
2.3.解除共享映射区
int shmdt(const void *shmaddr);
功能: 将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)。
参数: shmaddr:共享内存映射地址。
返回值: 成功:返回0。 失败:返回 -1。
2.4.共享内存控制
int shmctl(int shmid, int cmd,struct shmid_ds *buf);
功能: 共享内存空间的控制。
参数: shmid:共享内存标识符。 cmd:函数功能的控制。 buf:shmid_ds数据类型的地址,用来存放或修改共享内存的属性。
cmd说明: IPC_RMID:删除。 IPC_SET:设置shmid_ds参数。 IPC_STAT:保存shmid_ds参数。 SHM_LOCK:锁定共享内存段(超级用户)。 SHM_UNLOCK:解锁共享内存段。
返回值: 成功:返回0。 失败:返回 -1。
注意: SHM_LOCK用于锁定内存,禁止内存交换。并不代表共享内存被锁定后禁止其它进程访问。其真正的意义是:被锁定的内存不允许被交换到虚拟内存中。 这样做的优势在于让共享内存一直处于内存中,从而提高程序性能.
3.参考代码
3.1.共享内存读操作
#include <stddef.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "shmdata.h"
int main(int argc,char *argv[])
{
int ret;
int shmid;
void *shm = NULL;
struct shared_use_st *shared;
shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid < 0)
{
printf("shmget failed...\r\n");
exit(EXIT_FAILURE);
}
shm = shmat(shmid,0,0);
if(shm < 0)
{
printf("shmat failed...\r\n");
exit(EXIT_FAILURE);
}
printf("\nMemory attached at %X\n", (int)shm);
shared = (struct shared_use_st *)shm;
shared->written =0;
while(1)
{
if(shared->written == 1)
{
printf("You wrote: %s",shared->text);
sleep(1);
shared->written = 0;
if(strncmp(shared->text,"end",3) == 0)
{
break;
}
}
else
{
sleep(1);
}
}
ret = shmdt(shm);
if(ret < 0)
{
printf("shmdt failed...\r\n");
exit(EXIT_FAILURE);
}
ret = shmctl(shmid,IPC_RMID,0);
if(ret < 0)
{
printf("shmctl(IPC_RMID) failed...\r\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
return 0;
}
3.2.共享内存写操作
#include <stddef.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "shmdata.h"
int main(int argc,char *argv[])
{
int ret;
int shmid;
void *shm = NULL;
struct shared_use_st *shared = NULL;
char buffer[BUFSIZ + 1];
shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid < 0)
{
printf("shmget failed...\r\n");
exit(EXIT_FAILURE);
}
shm = shmat(shmid,(void *)0,0);
if(shm < 0)
{
printf("shmat failed...\r\n");
exit(EXIT_FAILURE);
}
printf("Memory attched at %X\n", (int)shm);
shared = (struct shared_use_st *)shm;
while(1)
{
while(shared->written == 1)
{
sleep(1);
printf("Waiting...\r\n");
}
printf("Enter some text: ");
fgets(buffer,BUFSIZ,stdin);
strncpy(shared->text,buffer,TEXT_SZ);
shared->written = 1;
if(strncmp(buffer,"end",3) == 0)
{
break;
}
}
if(shmdt(shm) == -1)
{
printf("shmdt failed...\r\n");
}
sleep(2);
exit(EXIT_SUCCESS);
return 0;
}
3.3…共享内存头文件
#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#define TEXT_SZ 2048
struct shared_use_st
{
int written;
char text[TEXT_SZ];
};
#endif
**注意:**需要开启两个终端,先运行写操作,再运行读操作,然后再写操作运行之后输入数据,并回车,可在读操作看到对应得数据。
|