共享内存
它是不同进程之间共享的内存区域
共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,它是在多个进程之间对内存段进行映射的方式实现内存共享的
是IPC最快的方式
共享内存方式直接将某内存段进行映射,多个进程间的共享内存是同一块的物理空间,仅仅是地址不同而已,因此不需要进行复制,可以直接使用此段空间
共享内存的特点
(1)共享内存就是允许两个不相关的进程访问同一个内存
(2)共享内存是两个正在运行的进程之间共享和传递数据的最有效的方式
(3)不同进程之间共享的内存通常安排为同一段物理内存
(4)共享内存不提供任何互斥和同步机制,一般用信号量对临界资源进行保护。
(5)接口简单
查看共享内存:ipcs -m
第一列就是共享内存的key;
第二列是共享内存的编号shmid;
第三列就是创建的用户owner;
第四列就是权限perms;
第五列为创建的大小bytes;
第六列为连接到共享内存的进程数nattach;
第七列是共享内存的状态status。其中显示“dest”表示共享内存段已经被删除,但是还有用户在使用它,当该段内存的mode字段设置为 SHM_DEST时就会显示“dest”。当用户调用shmctl的IPC_RMID时,内存先查看多少个进程与这个内存关联着,如果关联数为0,就会销 毁这段共享内存,否者设置这段内存的mod的mode位为SHM_DEST,如果所有进程都不用则删除这段共享内存。
共享内存数据结构
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};
共享内存操作函数
共享内存是通过把同一块内存分别映射到不同的进程空间中实现进程间通信,而共享内存本身不带任何互斥与同步机制,但当多个进程同时对同一内存进行读写操作时会破坏该内存的内容,所以在实际中,同步与互斥进制需要用户来完成
-
shmget()函数
功能:用来创建共享内存
函数原型:
#include<sys/ipc.h>
#incldue<sys/shm.h>
int shmget(key_t key,size_t size int shmflg);
函数shmget()的返回值:成功返回共享内存段的标识码,失败返回-1;
该函数参数有3个:
第一个参数key:共享内存段的名字,与消息队列类似,用ftok()函数产生;
第二个参数size:共享内存的大小;
第三个参数shmflg:它有两个取值IPC_CREAT 和 IPC_EXCL ;
单独使用IPC_CREAT,如不存在则果消息队列不存在,则创建之,如果存在则打开返回;
单独使用IPC_EXCL是没有意义的,两个同时使用,如果消息队列不存在则创建之,如果存在则出错返回。
例如:int shmid = shmget(key,pagesize,IPC_CREAT | IPC_EXCL | 0666);
创建一个大小为pagesize(getpagesize()函数获取内存页大小)个字节的权限为0666(所有用户可读可写)的共享存储空间,并返回一个整型共享存储标识符,如果key值(由ftok()函数产生)已经存在有共享存储空间了,则出错返回-1。
-
shmat()函数
功能:用来将内存段连接到进程地址空间
函数原型:
#include<sys/types.h>
#include<sys/shm.h>
void * shmat(int shmid,const void *shmaddr,int shmglg);
shmat()函数的返回值:成功返回一个指针,指向共享内存的第一个字节;失败返回-1;
shmat()函数有3个参数:
第一个参数shmid:共享内存的标识码由shmget()函数返回;
第二个参数shmaddr:指定连接的地址。若shmaddr取NULL,表示核心自动选择一个地址;若不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址;若不为NULL且shmflg设置了SHM_RND标记则连接的地址会自动向下调整为SHMLBA的整数倍。
第三个参数shmflg:它有两个可能取值:SHM_RND 和 SHM_RDONLY(只读共享内存);
例如:
void *shm=shmat(shmid,NULL,0);
将共享内存,映射到进程的内存空间,第三个参数0代表可读写;
-
shmdt()函数
功能:将共享内存段与当前进程脱离
函数原型:
int shmdt(const void *shmaddr);
shmad()函数返回值:成功返回0,失败返回-1;
参数:shmaddr 表示shmat()函数返回的指针
例如:
shmdt(shm);
将共享内存shm和进程脱离;
-
shmctl()函数
功能:用于控制共享内存;
函数原型:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmctl(int shmid,int cmd, struct shmid_ds *buf);
函数返回值:成功返回0,失败返回-1;
该函数有3个参数:
第一个参数shmid:共享内存的标识码;
第二个参数cmd:有三个可取的值:
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中;
IPC_SET:进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值
IPC_RMID:删除共享内存段
第三个参数 buf:是一个结构指针,它指向共享内存模式和访问权限的结构;
例如:
shmctl(shmid,IPC_RMID,0);
删除共享内存shmid;
目录