共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号,配合使用,来实现进程间的同步和通信。
C:
相关函数:
shmget函数:用于开辟或指向一块共享内存,返回获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域。
keyt key: 共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。
如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。
int size: 以字节为单位指定需要共享的内存容量。
int flag: 包含9个比特的权限标志,它是这块内存的模式(mode)以及权限标识。
模式可取如下值:
IPC_CREAT 新建(如果已创建则返回目前共享内存的id)
IPC_EXCL 与 IPC_CREAT结合使用,如果已创建则返回错误
将“模式” 和“权限标识”进行或运算,做为第三个参数。如:IPC_CREAT | IPC_EXCL | 0640
其中0640为权限标识,4/2/1 分别表示读/写/执行3种权限,第一个0是UID,第一个6(4+2)表示拥
有者的权限,第二个4表示同组权限,第3个0表示他人的权限。
函数调用成功时返回共享内存的ID,失败时返回-1。
注:创建共享内存时,shmflg参数至少需要 IPC_CREAT | 权限标识,如果只有IPC_CREAT 则申请的地址都是
k=0xffffffff,不能使用;
shmat函数:用来允许本进程访问一块共享内存的函数。
第一次创建共享内存时,它不能任何进程访问,要想启用对该共享内存的访问,必须将其连接到一个进程的地址空间中。
shmat函数就是用来完成此工作的。
int shmid : 共享内存的ID,即共享内存的标识。
char *shmaddr: 共享内存连接到进程中的起始地址,如果shmaddr为NULL,内核会把共享内存映射到系统选定的地
址空间中;如果shmaddr不为NULL,内核会把共享内存映射到shmaddr指定的位置。
注:一般情况下我们很少需要控制共享内存连接的地址,通常都是让系统来选择一个地址,否则就会使应
用程序对硬件的依赖性过高。所以一般把shmaddr设为NULL。
int shmflag : 本进程对该内存的操作模式,可以由两个取值:SHM_RND和SHM_RDONLY。SHM_RND为读写模式,
SHM_RDONLY是只读模式。需要注意的是,共享内存的读写权限由它的属主、它的访问权限和当
前进程的属主共同决定。如果当shmflg & SM_RDONLY为true时,即使该共享内存的访问权限允许写操
作,它也不能被写入。该参数通常会被设为0。
函数调用成功时,返回共享内存的起始地址,失败时返回-1。
shmdt函数:用于函数删除本进程对这块内存的使用。
shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。
char *shmaddr 是那块共享内存的起始地址。
函数调用成功时返回0,失败时返回-1。
shmctl函数: 控制对这块共享内存的使用。
int shmid: 共享内存的ID,即共享内存标识。
int cmd : 控制命令,表示要采取的动作,可取值如下:
IPC_STAT 得到共享内存的状态:把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET 改变共享内存的状态:把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID 删除共享内存段
shmid_ds结构至少包含以下成员:
struct shmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
uid_t shm_perm.mode;
}
struct shmid_ds *buf: 一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。
如果要改变共享内存的状态,用这个结构体指定。
函数调用成功时返回0,失败时返回-1
实现内存共享传输数据
先运行,然后输入
#include <signal.h>
#include "headfile.h"
int shmid;
void rmid(int sig)
{
//delete the share memory
shmctl(shmid,IPC_RMID,NULL);
}
int main(int argc,char **argv)
{
//register the signal
signal(SIGINT,rmid);
//get the key
key_t key = ftok(PROJ_PATH,PROJ_ID);
//create the share memory
shmid = shmget(key,SHMSIZE,IPC_CREAT|0666);
//map the share memory and return the address
char *p = shmat(shmid,NULL,0);
bzero(p,SHMSIZE);
pid_t pid = getpid();
memcpy(p,&pid,sizeof(pid_t));
fgets(p+sizeof(pid_t),SHMSIZE,stdin);
pause();
return 0;
}
再运行
#include "headfile.h"
int main(int argc , char **argv)
{
//get the key
key_t key = ftok(PROJ_PATH,PROJ_ID);
//create the shared memory
int shmid = shmget(key,SHMSIZE,0666);
//map the share memory and return the address
char *p = shmat(shmid,NULL,0);
printf("From SHM: %s",p+sizeof(pid_t));
//send the SIGINT signal
kill(*((pid_t *)p),SIGINT);
printf("send the SIGINT\n");
//detach the share memory in process
shmdt(p);
printf("detach the share memory\n");
return 0;
}