System V IPC(3)-共享内存

时间:2022-07-02 00:49:25

一.概述                                                   

1.共享内存允许多个进程共享物理内存的同一块内存区。

2.与管道和消息队列不同,共享内存在用户内存空间,不需要内核介入。降低了内核和用户缓冲区的数据复制开销。所以这种IPC速度比较快。

3.多个进程共享内存时需要其他同步机制来控制临界区,如上一篇的信号量

二.函数接口                                            

1.创建或打开共享内存

 #include <sys/shm.h>

 int shmget(key_t key, size_t size, int shmflg);

key和shmflg同消息队列和信号量一样,这里不再叙述。

size:需要分配内存的大小

2.使用共享内存

 #include <sys/shm.h>

 void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid:shmget()返回的值

shmaddr:把刚刚创建的内存指向该指针。如果是NULL,内核会自动选择。

shmflg:如果shmaddr不为NULL,shmflg控制shmaddr如果指向内存。如内存只读,计算内存地址倍数等,可以查看man手册。

3.分离共享内存

 #include <sys/shm.h>

 int shmdt(const void *shmaddr);

shmaddr是该进程指向共享内存的指针。把该共享内存从该进程分离,即该共享内存和该进程没有联系了。分离后,共存内存依然存在。

4.控制共享内存

 #include <sys/shm.h>

 int shmctl(int shmid, int cmd, struct shmid_ds *buf);

cmd和消息队列一样,IPC_RMID是删除共享内存。

三.简单例子                                            

我们写2个小程序,第一个创建和拷贝数据到共享内存,第二个读取共享内存数据并删除共享内存。

1.创建和拷贝

 /**
  * @file shm1.c
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/shm.h>

 #define SHARE_MEM_BUF_SIZE 1024

 void err_exit(const char *err_msg)
 {
     printf("error:%s\n", err_msg);
     exit();
 }

 int main(void)
 {
     int shm_id;
     void *share_mem;
     ";

     shm_id = shmget(IPC_PRIVATE, SHARE_MEM_BUF_SIZE,  | IPC_CREAT);
     )
         err_exit("shmget()");

     printf("shm_id:%d\n", shm_id);

     /* 把创建的共享内存指向该程序的一个指针 */
     share_mem = shmat(shm_id, NULL, );
     )
         err_exit("shmat()");

     /* 拷贝数据到共享内存 */
     memcpy((char *)share_mem, text, strlen(text));

     /* 分离共享内存 */
     )
         err_exit("shmdt()");

     ;
 }

2.读取并删除

 /**
  * @file shm2.c
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/shm.h>

 #define SHARE_MEM_BUF_SIZE 1024

 void err_exit(const char *err_msg)
 {
     printf("error:%s\n", err_msg);
     exit();
 }

 int main(int argc, const char *argv[])
 {
     )
     {
         printf(]);
         exit();
     }

     void *share_mem;
     ]);

     /* 把创建的共享内存指向该程序的一个指针 */
     share_mem = shmat(shm_id, NULL, );
     )
         err_exit("shmat()");

     /* 读取数据 */
     printf("read data:%s\n", (char *)share_mem);

     /* 分离共享内存 */
     )
         err_exit("shmdt()");

     /* 删除共享内存 */
     ) == -)
         err_exit("shmctl()");

     ;
 }

四.实验                                                   

1.shm1.c用IPC_PRIVATE方式让内核自动创建一个key,并分配1024字节内存。第36行把"123456"拷贝到共享内存。

2.shm2.c从命令行来指定要使用的共享内存,第35行读取数据,第42行删除数据。

3.运行shm1后,可以得到共享内存的shmid,可以用ipcs -m | grep 'xxx'查看:

System V IPC(3)-共享内存

可以看到我们分配的1024字节内存。

4.运行shm2接收shmid=50954258的数据并删除共享内存,再用ipcs -m | grep 'xxx'查看:

System V IPC(3)-共享内存

可以看到读取了"123456"数据,用ipcs查看时,已被删除。