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,由父进程读出

 

 
  
  1. #include<sys/types.h> 
  2. #include<sys/ipc.h> 
  3. #include<sys/shm.h> 
  4. #include<stdio.h> 
  5. #include<sys/stat.h> 
  6. #include<stdlib.h> 
  7.  
  8. #define KEY 1234 
  9. #define SIZE 2048 
  10. int main() 
  11.   pid_t pid; 
  12.   int shmid; /*共享内存ID*/ 
  13.   char * shmaddr; /*连接地址*/ 
  14.   struct shmid_ds buf; 
  15.   
  16.   shmid=shmget(KEY,SIZE,IPC_CREAT|0600);/*建立共享内存*/ 
  17.   pid=fork(); 
  18.   if(pid<0) 
  19.    { 
  20.      perror("fork error!\n"); 
  21.     exit(0); 
  22.    } 
  23.   if(pid==0)/*子进程将"Hello world!\n写入共享内存"*/ 
  24.   { 
  25.     shmaddr=shmat(shmid,NULL,0);/*子进程与共享内存连接*/ 
  26.     sprintf(shmaddr,"Hello world!\n");/*写入共享内存*/ 
  27.     printf("Messgae have been write to shared memory!\n"); 
  28.     shmdt(shmaddr);/*断开子进程与共享内存的连接*/ 
  29.     exit(0); 
  30.    } 
  31.  
  32.    sleep(3);/*待子进程结束*/ 
  33.    shmctl(shmid,IPC_STAT,&buf);/*共享内存状态存入buf中*/ 
  34.    shmaddr=(char *)shmat(shmid,NULL,0);/*父进程与共享内存连接*/ 
  35.     
  36.    printf("Message in shared memory:%s\n",shmaddr);/*输出共享内存数据*/ 
  37.    shmdt(shmaddr);/*断开父进程与共享内存的连接*/ 
  38.    shmctl(shmid,IPC_RMID,NULL);/*删除共享内存*/ 

输出

Messgae have been write to shared memory!
Message in shared memory:Hello world!

另外也可重新创建一个进程,读取该共享内存的数据。将上个c文件中最后一行删除,使得程序结束时不删除共享内存,再执行下面程序,使新进程读取共享内存数据。(共享内存需一致,创建时KEY相同)

 

 
  
  1. #include<sys/types.h> 
  2. #include<sys/ipc.h> 
  3. #include<sys/shm.h> 
  4. #include<stdio.h> 
  5. #include<sys/stat.h> 
  6. #include<stdlib.h> 
  7.  
  8. #define KEY 1234 
  9. #define SIZE 2048 
  10. int main() 
  11.   pid_t pid; 
  12.   int shmid; /*共享内存ID*/ 
  13.   char * shmaddr; /*连接地址*/ 
  14.   struct shmid_ds buf; 
  15.   
  16.   shmid=shmget(KEY,SIZE,IPC_CREAT|0600);/*建立共享内存*/ 
  17.  
  18.    shmctl(shmid,IPC_STAT,&buf);/*共享内存状态存入buf中*/ 
  19.    shmaddr=(char *)shmat(shmid,NULL,0);/*进程与共享内存连接*/ 
  20.     
  21.    printf("Message in shared memory:%s\n",shmaddr);/*输出共享内存数据*/ 
  22.    shmdt(shmaddr);/*断开进程与共享内存的连接*/ 
  23.    shmctl(shmid,IPC_RMID,NULL);/*删除共享内存*/