【linux】共享内存

2/22/2017来源:ASP.NET技巧人气:1229

分配共享内存

使用shmget函数来分配,首先来看shmget里的参数

该函数的第一个参数是一个用来标识共享内存块的键值。彼此无关的进程可以通过指定同一个键以获取对同一个共享内存块的访问。不幸的是,其它程序也可能挑选了同样的特定值作为自己分配共享内存的键值,从而产生冲突。用特殊常量ipC_PRIVATE作为键值可以保证系统建立一个全新的共享内存块。 该函数的第二个参数指定了所申请的内存块的大小。因为这些内存块是以页面为单位进行分配的,实际分配的内存块大小将被扩大到页面大小的整数倍。 第三个参数是一组标志,通过特定常量的按位或操作来shmget。这些特定常量包括: IPC_CREAT:这个标志表示应创建一个新的共享内存块。通过指定这个标志,我们可以创建一个具有指定键值的新共享内存块。 IPC_EXCL:这个标志只能与 IPC_CREAT 同时使用。当指定这个标志的时候,如果已有一个具有这个键值的共享内存块存在,则shmget会调用失败。也就是说,这个标志将使线程获得一个“独有”的共享内存块。如果没有指定这个标志而系统中存在一个具有相同键值的共享内存块,shmget会返回这个已经建立的共享内存块,而不是重新创建一个。 释放共享内存

使用shmctl函数来释放,下面看看shmctl的参数

该函数的第一个参数是一个共享内存块标识。 要获取一个共享内存块的相关信息,则为该函数传递 IPC_STAT 作为第二个参数,同时传递一个指向一个 struct shmid_ds 对象的指针作为第三个参数。 要删除一个共享内存块,则应将 IPC_RMID 作为第二个参数,而将 NULL 作为第三个参数。当最后一个绑定该共享内存块的进程与其脱离时,该共享内存块将被删除。 您应当在结束使用每个共享内存块的时候都使用 shmctl 进行释放,以防止超过系统所允许的共享内存块的总数限制。调用 exit 和 exec 会使进程脱离共享内存块,但不会删除这个内存块。 查看系统中共享内存的指令为ipcs -m

输出共享内存指令为 ipcrm -m 共享内存的id,这里就不再做演示了

下面用代码来实现共享内存的测试

shm.c

#ifndef _SHM_
#define _SHM_
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#include<sys/wait.h>
#define PATHTYPE "."
#define PROJID 88
#define SIZE 4096*1
int creatShm();
int getShm();
char* atShm(int shmId);
int dtShm(char*addr);
int destoryShm(int shmId);
#endif

shm.c

#include"shm.h"
static int commShm(int flg)
{
    key_t k=ftok(PATHTYPE,PROJID);
	if(k<0){
		perror("ftok");
		return -1;
	}
	int semId=shmget(k,SIZE,flg);
	if(semId<0)
	{
	perror("shmget");
	return -2;
	//printf("get share memory error!\n");
	}
	//else
	//{
	//	printf("get share memory success!\n");
	//}
		return semId;
}
int creatShm()
{
 return commShm(IPC_CREAT|IPC_EXCL);

}
int getShm(){

	return commShm(IPC_CREAT);
}
char* atShm(int shmId)
{
return (char*)shmat(shmId,NULL,0);
}
int dtShm(char*addr)
{
	return shmdt(addr);
}
int destoryShm(int shmId)
{
	if(shmctl(shmId,IPC_RMID,NULL)<0)
	{
		perror("shmctl");
		return -1;
	}
	return 0;
}
上面的代码是生成共享内存的代码

以下是发送方代码client.c

#include"shm.h" 
int main()
{
	int shmid=creatShm();
    char*mem=	shmat(shmid,NULL,0);
	while(1)
	{
		sleep(1);
		printf("%s\n",mem);
	}
	shmdt(mem);
	destoryShm(shmid);
	return 0;
}
以下是接收方server.c

#include"shm.h"
int main()
{
	int shmid=creatShm();
    char*mem=	shmat(shmid,NULL,0);
	while(1)
	{
		sleep(1);
		printf("%s\n",mem);
	}
	shmdt(mem);
	destoryShm(shmid);
	return 0;
}

本工程Makefile

cli=client
ser=server
cc=gcc
serSrc=shm.c server.c
cliSrc=shm.c client.c
.PHONY:all
all:$(cli) $(ser)

$(cli):$(cliSrc)
	$(cc) -o $@ $^
$(ser):$(serSrc)
	$(cc) -o $@ $^
.PHONY:clean
clean:
	rm -f $(cli) $(ser)
测试结果

下面进行监控查看共享内存信息

我们发现这个共享内存的shmid为shmid,挂载了两个进程nattch为2

以上便是共享内存的部分知识