2.共享内存

一、概念  

共享内存:允许在系统内两个或多个进程共享同一块内存空间,并且数据不用在客户进程和服务器进程间复制,因此共享内存
                  是通信速度最快的一种IPC。
实现机制:一个进程在系统中申请开辟一块共享内存空间,然后使用这个共享内存空间的各个进程分别打开这个共享内存空间,
                 并将这个内存空间映射到自己的进程空间上,这样各个进程就可以共同使用这个共享内存空间,就如同使用自己进程
                 地址空间的内存一样,达到对内存的读写操作。  
共享内存相关函数:
  头文件: #include <sys/ipc.h> #include <sys/shm.h>

   int shmget(key_t key, size_t size, int shmflg);        //1.创建或获取共享内存

   void *shmat(int shmid,const void* shmaddr,int shmflg);      //2.进程链接共享内存

   int shmdt(const void* shmaddr);            //3.共享内存与当前进程脱离开

   int shmctl(int shmid, int cmd, struct shmid_ds *buf);            //4.共享内存控制函数

二、函数参数介绍

  1.shmget函数 :创建或获取共享内存

          int  shmget(key_t key,size_t size, int shmflg);
     key: 创建或获取共享内存段的键值
          size: 共享的内存空间
          shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样
          如果共享内存创建成功,shmget将返回一个非负整数,即该段共享内存的标识码;如果失败,则返回“-1”
 
  2.shmmat函数 :内存段刚创建,任何进程都不能访问该内存段。只有当内存空间映射到进程空间中,该进程
          才能访问共享内存。(建立地址映射,进程连接)

     void* shmat(int shm_id, const void *shm_addr, int shmflg);
          shm_id: shmget返回的共享内存标识码
          shm_addr:把共享内存连接到当前进程去的时候准备放置它的那个地址
          注:  1.shmaddr为0,核心自动选择一个地址(一般自动设置)
                   2.shmaddr不为0且shmflg无SHM_RND标记,则以shmaddr为连接地址。
          shmflg是一组按位OR(或)在一起的标志。它的两个可能取值是SHM_RND和SHM_RDONLY
       调用成功,返回指针,指针指向共享内存的第一个字节;失败,则返回“-1”
      其中: 
          1.在fork() 后,子进程继承已连接的共享内存
                        2.在exec后,已连接的共享内存会自动脱离(detach)
                        3.在结束进程后,已连接的共享内存会自动脱离(detach)  
 

  3.shmdt函数 :共享内存与当前进程脱离开

        int  shmdt(const void *shm_addr);
     shm_addr: 由shmat返回的地址指针
     操作成功,返回“0”,失败则返回“-1”
     注:脱离共享内存并不等于删除它,只是当前进程不能再继续访问它而已。

  4.shmctl函数 :共享内存控制函数

     int  shmctl(int shm_id,int command, struct shmid_ds *buf);

     shm_id: 由shmget返回的共享内存标识码
     command:将要采取的动作(有三个可取值)
                           
    buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
    操作成功,返回0,失败则返回-1
 

三、代码实例

创建共享内存,并不同进程对创建的共享内存读写操作,最后删除该共享内存。

1.创建共享内存: shmget.c文件

 1 #include "stu.h"
 2 #include<stdio.h>
 3 #include<sys/ipc.h>
 4 #include<sys/shm.h>
 5 #include<stdlib.h>
 6 
 7 int main()
 8 {
 9     int shmid = shmget((key_t)0x1001, sizeof(stu_t)*10, IPC_CREAT | IPC_EXCL | 0666);
10     if(shmid == -1)
11     {
12         perror("shmget");
13         exit(EXIT_FAILURE);
14     }
15     printf("shared memory created success, shmid = %d", shmid);
16     return 0;
17 }
View Code

2.往共享内存写数据  shmput.c文件

 1 #include "stu.h"
 2 #include<stdio.h>
 3 #include<sys/ipc.h>
 4 #include<sys/shm.h>
 5 #include<stdlib.h>
 6 #include<unistd.h>
 7 #include<string.h>
 8 
 9 /********  共享内存链接 ***********
10  *1.获取shmid
11  *2.连接共享内存
12  *3.封装数据结构
13  *4.写数据
14  ***********************************/
15 int main(int argc, char* argv[])
16 {
17     //1.获取shmid
18     int shmid = shmget((key_t)0x1001, 10, 0);
19     if(shmid == -1)
20     {
21         perror("shmget");
22         exit(EXIT_FAILURE);
23     }
24     //2.连接共享内存
25     void *pShm = shmat(shmid, 0, 0);
26     if(pShm == (void*)-1)
27     {
28         perror("shmat");
29         exit(EXIT_FAILURE);
30     }
31     //3.封装数据结构
32     stu_t aStu = {1001, "Tom"};
33     //4.写数据
34     memcpy(pShm, &aStu, sizeof(stu_t));
35     //5.用完了就要断开连接
36     if(shmdt(pShm)!= 0)
37     {
38         perror("shmdt");
39         exit(EXIT_FAILURE);
40     }
41     return 0;
42 }
View Code

3.从共享内存读数据 shmread.c文件

 1 #include "stu.h"
 2 #include<stdio.h>
 3 #include<sys/ipc.h>
 4 #include<sys/shm.h>
 5 #include<stdlib.h>
 6 #include<unistd.h>
 7 #include<string.h>
 8 
 9 /********  共享内存链接 ***********
10  *1.获取shmid
11  *2.连接共享内存
12  *3.封装数据结构
13  *4.写数据
14  ***********************************/
15 
16 int main(int argc, char* argv[])
17 {
18     //1.获取shmid
19     int shmid = shmget((key_t)0x1001, 10, 0);
20     if(shmid == -1)
21     {
22         perror("shmget");
23         exit(EXIT_FAILURE);
24     }
25     //2.连接共享内存
26     void *pShm = shmat(shmid, 0, 0);
27     if(pShm == (void*)-1)
28     {
29         perror("shmat");
30         exit(EXIT_FAILURE);
31     }
32     //3.封装数据结构
33     stu_t aStu = {0};
34     //4.写数据
35     memcpy(&aStu, pShm, sizeof(stu_t));
36     printf("get shmid = %d, name = %s\n", aStu.id, aStu.name);
37     //5.用完了就要断开连接
38     if(shmdt(pShm)!= 0)
39     {
40         perror("shmdt");
41         exit(EXIT_FAILURE);
42     }
43     return 0;
44 }
View Code

4.删除共享内存 shmctl.c文件

 1 #include "stu.h"
 2 #include<stdio.h>
 3 #include<sys/ipc.h>
 4 #include<sys/shm.h>
 5 #include<stdlib.h>
 6 
 7 int main()
 8 {
 9     int shmid = shmget((key_t)0x1001, 10 , 0);
10     if(shmid == -1)
11     {
12         perror("shmget");
13         exit(EXIT_FAILURE);
14     }
15     if(shmctl(shmid, IPC_RMID, NULL) == -1)
16     {
17         perror("shmctl");
18         exit(EXIT_FAILURE);
19     }
20     return 0;
21 }
View Code

5.公有文件: stu.h

 1 #ifndef _STU_H
 2 #define _STU_H
 3 
 4 typedef struct student_s
 5 {
 6     int id;
 7     char name[32];
 8 }stu_t;
 9 
10 #endif
View Code

 

Linux下运行图:

                               

 

 

posted @ 2018-10-01 20:45  louis-gx  阅读(452)  评论(0编辑  收藏  举报