有关函数shmget创建一个共享内存对象并返回共享内存标识符或得到一个共享内存标识符
原型:int shmget(key_t key,size_t size,int shmflg);
返回值:失败返回-1,成功返回标识
参 数: key:一般由系统调用fotk获得,为0(IPC_PRIVATE)时会建立新共享内存对象
size:要创建或得到的共享内存对象的大小,以字节为单位,和页(4k)对齐
shmflg :
0 取共享内存标识符,若不存在则函数会报错
IPC_CREAT 如果内核中不存在键值与key相等的共享内存,则新建一个共享内 存;如果存在这样的共享内存,返回此共享内存的标识符
IPC_CREAT|IPC_EXCL 如果内核中不存在键值与key相等的共享内存,则新建 一个消息队列;如果存在这样的共享内存则报错
=========================================================================
shmat连接共享内存标识符为shmid的共享内存,链接成功后把共享内存区地址映射到进程地 址空间,随后该进程可以像访问本地空间一样来访问这块内存
原型:void *shmat(int shmid,const void *shmaddr,int shmflg);
返回值:失败返回-1,成功返回shmid所标识的共享内存的映射到虚拟地址空间的地址
参 数:shmid:共享内存的标识
shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL时内核自己决定一 个合适的地址位置
shmflg:
SHM_RDONLY:只读模式
其它:读写模式
=========================================================================
shmdt 与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存
原型:int shmdt(const void*shmaddr);
返回值:失败返回-1,成功返回0
参数:shmaddr:shmat()的返回值(共享内存区地址映射到进程的地址)
=========================================================================
shmctl 对共享内存的管理与控制
原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
返回值:失败返回-1,成功返回0
参数:shmid:共享内存的标识
cmd:
IPC_RMID:删除这片共享内存
IPC_STAT:得到共享内存的状态,并复制到第三个参数buf所指向的结构体中
IPC_SET:改变共享内存的状态,把buf所指向的结构体中的uid、gid、mode复制到共享内 存的shmid_ds结构中
buf:共享内存管理结构体
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
time_t shm_atime;
time_t shm_dtime;
time_t shm_ctime;
pid_t shm_cpid;
pid_t shm_lpid;
shmatt_t shm_nattch; ...
};
=========================================================================
代码实现:
shm.h#ifndef _SHM_H_
#define _SHM_H_
#include
#include
#include
#include
#include
#include
#define __PATH__ "."
#define __PROJ_ID__ 0x26
#define SIZE 4096
int creat_shm(int _size);
int get_shm(int _size);
int destory_shm(int _shm_id);
#endif
shm.c#include"shm.h"
static int comm_shm(int _size,int flags)
{
key_t _key=-1;
if((_key=ftok(__PATH__,__PROJ_ID__))<0){
perror("ftok");
return -1;
}
int _shm_id=-1;
if((_shm_id=shmget(_key,_size,flags))<0){
perror("shmget");
return -1;
}
return _shm_id;
}
int creat_shm(int _size)
{
return comm_shm(_size,IPC_CREAT|IPC_EXCL|0666);
}
int get_shm(int _size)
{
return comm_shm(_size,IPC_CREAT);
}
int destory_shm(int _shm_id)
{
if(shmctl(_shm_id,IPC_RMID,NULL)<0){
perror("shmctl");
return -1;
}
return 0;
}
shm_server.c#include"shm.h"
int main()
{
int _shm_id=creat_shm(SIZE);
char *addr=(char*)shmat(_shm_id,0,0);
sleep(5);
int j=0;
while(1){
while(j<128){
printf("%c ",addr[j++]);
}
printf("\n");
break;
}
sleep(8);
if(shmdt(addr)<0){
perror("attach is failed!\n");
}
printf("attach has success!\n");
sleep(3);
destory_shm(_shm_id);
printf("destory successed\n");
return 0;
}
shm_client.c#include"shm.h"
int main()
{
int _shm_id=get_shm(SIZE);
sleep(2);
char *addr=(char*)shmat(_shm_id,0,0);
int i=0;
while(i<128){
addr[i++]=i;
}
sleep(10);
if(shmdt(addr)<0){
perror("attach is failed!\n");
}
printf("attach has success!\n");
return 0;
}
Makefile.PHONY:all
all:shm_server shm_client
shm_server:shm_server.c shm.c
gcc -o [email protected] $^
shm_client:shm_client.c shm.c
gcc -o [email protected] $^
.PHONY:clean
clean:
rm -rf shm_server shm_client
运行server端结果:
运行client端结果:
运行前系统中所有的共享内存段(因为我们只关注它的变化,因此后面的截图只截了一部分)
运行中: 可以看到系统中多了shmid为1048590的Shared Memory,它的nattch为1
shmid为1048590的Shared Memory,它的nattch增加为2
shmid为1048590的Shared Memory,它的nattch减少为1
shmid为1048590的Shared Memory,它的nattch减少为0
shmid为1048590的Shared Memory,不存在了