系统调用mmap通过映射一个普通文件实现共享内存。System V 则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件。执行过程是先调用shmget,再调用shmat。对于每个共享的内存区,内核维护如下的信息结构,定义在
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
time_t shm_atime; /* last attach time */
time_t shm_dtime; /* last detach time */
time_t shm_ctime; /* last change time */
unsigned short shm_cpid; /* pid of creator */
unsigned short shm_lpid; /* pid of last operator */
short shm_nattch; /* no. of current attaches */
/* the following are private */
unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct vm_area_struct *attaches; /* descriptors for attaches */
};
使用共享内存的流程:
#include
#include
/*
创建一个新的内存共享区或者访问一个已经存在的共享内存区
返回共享内存区标识符
*/
int shmget(key_t key, size_t size, int shmflg);
/*
创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间
*/
void *shmat(int shmid, const void *shmaddr,int shmflg);
/*
当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区
*/
int shmdt(const void *shmaddr);
/*
对内存区进行多种操作
cmd取值:
IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它
IPC_SET:给指定的共享内存区设置其shmid_ds结果成员
IPC_STAT:通过buff参数向调用者返回所指定共享内存区当前的shmid_ds结构
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
调用System V API编写程序进行测试:
程序1:调用shmget函数使用指定的路径名和长度创建一个共享内存区,程序如下:
#include
#include
#include
#include
#include
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
int main(int argc,char *argv[])
{
int c,id,oflag;
char *ptr;
size_t length;
oflag = SVSHM_MODE | IPC_CREAT;
while(( c = getopt(argc,argv,"e")) != -1)
{
switch(c)
{
case 'e':
oflag |= O_EXCL;
break;
}
}
if (optind != argc -2)
{
printf("usage: shmget [-e] .
");
exit(0);
}
length = atoi(argv[optind + 1]);
//创建由用户指定其名字和大小的共享内存区
id = shmget(ftok(argv[optind],0),length,oflag);
//把该内存区连接到当前进程的地址空间
ptr = shmat(id,NULL,0);
exit(0);
}
程序2:调用shmctl指定IPC_RMID命令,从系统中删除一个共享内存区,程序如下:
#include
#include
#include
#include
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
int main(int argc,char* argv[])
{
int id;
if(argc != 2)
{
printf("usage: shmrmid
");
exit(0);
}
//打开共享内存区
id = shmget(ftok(argv[1],0),0,SVSHM_MODE);
//从系统中删除由id标识的共享内存区
shmctl(id,IPC_RMID,NULL);
exit(0);
}
程序3:往共享内存区中写入一个模式,调用shmctl指定IPC_STAT命令格式,程序如下:
#include
#include
#include
#include
#include
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
int main(int argc,char *argv[])
{
int i,id;
struct shmid_ds buff;
unsigned char *ptr;
if(argc != 2)
{
printf("usage: shmwrite .
");
exit(0);
}
id = shmget(ftok(argv[1],0),0,SVSHM_MODE);
ptr = shmat(id,NULL,0);
shmctl(id,IPC_STAT,&buff); //获取共享内存区大小
for(i=0;i
程序4:从共享内存中读出模式,程序如下:
#include
#include
#include
#include
#include
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
int main(int argc,char *argv[])
{
int i,id;
struct shmid_ds buff;
unsigned char c,*ptr;
if(argc != 2)
{
printf("usage: shmread .
");
exit(0);
}
id = shmget(ftok(argv[1],0),0,SVSHM_MODE);
ptr = shmat(id,NULL,0);
shmctl(id,IPC_STAT,&buff);
for(i=0;i
二者的差别是:
(1)Posix共享内存区是先调用shm_open然后再调用mmap,System V 共享内存区是先调用shmget再调用shmat。
(2)Posix共享内存区对象的大小可在任何时刻通过ftruncate修改,而System V 共享内存区对象的大小是在调用shmget创建时固定下来的。
更多Linux内核视频教程文档资料免费领取后台私信【内核】自行获取。
页面更新:2024-04-25
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号