linux下共享内存
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux下共享内存
SUNNY.MAN
共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间) 从而使得这些进程可以相互通信,进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时调用shmdt来卸载区段。注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。如果区段已经做了删除标记(在前面以IPC_RMID指令调用shmctl),而当前挂接数已经变为0,这个区段就会被移除。Linux中通过API函数shmget创建的共享内存一般都是在程序中使用shmctl来释放的,但是有时为了调试程序,开发人员可能通过Ctrl + C等方式发送中断信号来结束程序,此时程序申请的共享内存就不能得到释放,当然如果程序没有改动的话,重新运行程序时仍然会使用上次申请的共享内存,但是如果我们修改了程序,由于共享内存的大小不一致等原因会导致程序申请共享内存错误。因此,我们总是希望每次结束时就能释放掉申请的共享内存。
有两种方法可以用来释放共享内存:
第一种:如果总是通过Crtl+C来结束的话,可以做一个信号处理器,当接收到这个信号的时候,先释放共享内存,然后退出程序。
第二种:不管你以什么方式结束程序,如果共享内存还是得不到释放,那么可以通过linux命令ipcrm shm shmid来释放,在使用该命令之前可以通过ipcs -m命令来查看共享内存。
共享内存查看
使用ipcs命令,不加如何参数时,会把共享内存、信号量、消息队列的信息都
打印出来,如果只想显示共享内存信息,使用如下命令:
[root@localhost ~]# ipcs –m
同样共享内存的大小也可以用ipcs –lm来查看它的上限下限。
shmget( ) 创建一个新的共享内存区段
取得一个共享内存区段的描述符
shmctl( ) 取得一个共享内存区段的信息
为一个共享内存区段设置特定的信息
移除一个共享内存区段
shmat( ) 挂接一个共享内存区段
shmdt( ) 于一个共享内存区段的分离
同样共享内存的大小也可以用ipcs –lm来查看它的上限下限。我们主要也是关心三个变量,一个是一共可以建立多少个共享内存段,每个段都大可以多少,一共有多少内存可以共享。
使用下面的命令查看共享内存的大小:
max number of segments = 4096//总共可以有多少个段
max seg size (kbytes) = 4194303//一个段可以多大
max total shared memory (kbytes) = 1073741824//所有可以共享的内存大小
min seg size (bytes) =1
# cat /proc/sys/kernel/shmmax
修改共享内存大小:
临时修改:在root用户下执行
# echo 268435456 > /proc/sys/kernel/shmmax把共享内存大小设置为256MB;
永久修改:在root用户下修改/etc/rc.d/rc.local文件,加入下面一行:echo 268435456 > /proc/sys/kernel/shmmax
即可每次启动时把共享内存修改为256MB
Sndchar.c
#include
#include
#include
#include
#include
#include
#include
#define SHAREDATABASE 115 /*shared memory database key*/
#define SHAREBUFFER 116 /*shared buffer key*/
#define SHAREMEMORY 0x800000
#define MAX_TEXT 512
struct strshm
{
long head;
long tail;
};
int main(void)
{
int shm_id;
int running=1;
char *pchdatabase=NULL;
char *pchdatabaseori=NULL;
struct strshm * phead=NULL;
char buffer[MAX_TEXT];
long res=0;
shm_id=shmget(SHAREDATABASE,SHAREMEMORY,IPC_CREAT);//Create DataBase
if(shm_id==-1)
{
fprintf(stderr,"shmget failed with error: %d\n",errno);
exit(EXIT_FAILURE);
}
else
{
printf("shmget success shmid is %d\n",shm_id);
}
pchdatabase=(char*)shmat(shm_id,0,0); //Get Point
pchdatabaseori=pchdatabase;
phead=(struct strshm *)pchdatabase;
pchdatabase+=sizeof(struct strshm);
phead->head=sizeof(struct strshm);
phead->tail=sizeof(struct strshm);
while(running)
{
memset(buffer,0,MAX_TEXT);
printf("Enter some text: less than %d [type end stop]\n",MAX_TEXT);
fgets(buffer, MAX_TEXT, stdin);
res=strlen(buffer)+sizeof(long)+1;//'\0'
if((phead->head+res)<=(0x800000-sizeof(struct strshm)))
{
(*(long *)(pchdatabase+phead->head))=res;
phead->head+=sizeof(long);
memcpy(pchdatabase+phead->head,buffer,res-sizeof(long));
phead->head+=(res-sizeof(long));
printf("current head is %d,insert len=%d\n",phead->head,res);
}
if(strncmp(buffer, "end", 3) == 0)
{
break;
}
}
if(shmdt(pchdatabaseori) == -1)
perror(" detach error \n");
shmctl(shm_id, IPC_RMID, NULL);
return 0;
}
Rcvchar.c
#include
#include
#include
#include
#include
#include
#include