1.概述
共享内存是进程通信的一种方式。此方式会开辟一部分可以被多个进程共享访问的物理内存区域。进行通信的多个进程分别将该内存区域映射到自己的虚拟地址空间,则这些进程就可直接访问共享内存,从而达到通信的目的。这种方法进程间共享数据时最快,一个进程修改共享内存的数据后,其他进程可以立即看到。
2 通信步骤
头文件
#include<sys/ipc.h>
#include<sys/shm.h>
<1>创建共享内存
int shmget(key_t key, int size,int shmflg);
Shmget()用来取得参数key所关联的共享内存标识号。若key为IPC_PRIVATE则会创建新的共享内存,大小有size决定。若key不为IPC_PRIVATE,也不是已建立的共享内存,则会根据shmflg决定。
参数:key 0/IPC_PRIVATE
size 内存大小
shmflg 旗标位
返回值:成功返回共享内存识别id,失败返回-1,错误存储在errno中
<2>连接到共享内存
void * shmat(int shmid,const void *shmaddr,int shmflg);
shmat()用来将参数shmid所指的共享内存和目前的进程连接。
参数:shmid 与连接的共享内存标识码
shmaddr 0 内核自动选择一个地址
shmaddr 不为0且shmflg未指定SHM_RND,以shmaddr为连接地址
shmaddr 不为0但shmflg指定SHM_RND,shmaddr会调整为SHMLBA整数倍
返回值:成功返回已连接地址,失败返回-1,错误存储在errno中
<4>断开连接
int shmdt(const void *shmaddr);
shmdt()使当前进程与共享内存断开连接
参数:shmaddr为先前shmat()返回的共享内存地址
返回值 成功返回0,失败返回-1,错误存储在errno中
<3>对共享内存进行操作
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
shmctl()提供了几种控制共享内存的方式
参数:shmid 为共享内存的标识码
cmd 如下
IPC_STAT 得到共享内存的状态,
IPC_SET 改变共享内存的状态
IPC_RMID 删除共享内存
struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
返回值 成功返回0,失败返回-1,错误存储在errno中
举例
创建一个共享内存,子进程写入HelloWorld,由父进程读出
- #include<sys/types.h>
- #include<sys/ipc.h>
- #include<sys/shm.h>
- #include<stdio.h>
- #include<sys/stat.h>
- #include<stdlib.h>
- #define KEY 1234
- #define SIZE 2048
- int main()
- {
- pid_t pid;
- int shmid; /*共享内存ID*/
- char * shmaddr; /*连接地址*/
- struct shmid_ds buf;
- shmid=shmget(KEY,SIZE,IPC_CREAT|0600);/*建立共享内存*/
- pid=fork();
- if(pid<0)
- {
- perror("fork error!\n");
- exit(0);
- }
- if(pid==0)/*子进程将"Hello world!\n写入共享内存"*/
- {
- shmaddr=shmat(shmid,NULL,0);/*子进程与共享内存连接*/
- sprintf(shmaddr,"Hello world!\n");/*写入共享内存*/
- printf("Messgae have been write to shared memory!\n");
- shmdt(shmaddr);/*断开子进程与共享内存的连接*/
- exit(0);
- }
- sleep(3);/*待子进程结束*/
- shmctl(shmid,IPC_STAT,&buf);/*共享内存状态存入buf中*/
- shmaddr=(char *)shmat(shmid,NULL,0);/*父进程与共享内存连接*/
- printf("Message in shared memory:%s\n",shmaddr);/*输出共享内存数据*/
- shmdt(shmaddr);/*断开父进程与共享内存的连接*/
- shmctl(shmid,IPC_RMID,NULL);/*删除共享内存*/
- }
输出
Messgae have been write to shared memory!
Message in shared memory:Hello world!
另外也可重新创建一个进程,读取该共享内存的数据。将上个c文件中最后一行删除,使得程序结束时不删除共享内存,再执行下面程序,使新进程读取共享内存数据。(共享内存需一致,创建时KEY相同)
- #include<sys/types.h>
- #include<sys/ipc.h>
- #include<sys/shm.h>
- #include<stdio.h>
- #include<sys/stat.h>
- #include<stdlib.h>
- #define KEY 1234
- #define SIZE 2048
- int main()
- {
- pid_t pid;
- int shmid; /*共享内存ID*/
- char * shmaddr; /*连接地址*/
- struct shmid_ds buf;
- shmid=shmget(KEY,SIZE,IPC_CREAT|0600);/*建立共享内存*/
- shmctl(shmid,IPC_STAT,&buf);/*共享内存状态存入buf中*/
- shmaddr=(char *)shmat(shmid,NULL,0);/*进程与共享内存连接*/
- printf("Message in shared memory:%s\n",shmaddr);/*输出共享内存数据*/
- shmdt(shmaddr);/*断开进程与共享内存的连接*/
- shmctl(shmid,IPC_RMID,NULL);/*删除共享内存*/
- }