linux--共享内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ferlan/article/details/84190808

什么是共享内存?

共享内存是进程间通信的一种方式,而且是最快的IPC方式。

共享内存图解

在这里插入图片描述

为什么说共享内存是最快的IPC?(重点)

因为共享内存是直接将同一块物理内存映射到2个进程的虚拟地址空间当中,所以进行的数据传输的时候相较于其他通信方式,少了两步用户态到内核态数据拷贝的过程,因此称,共享内存是最快的进程间通信方式.
(像管道/消息队列等方式都是先将数据从用户态转入内核态,进行系统调用,然后再从内核态转出到用户态,让用户看见)

共享内存代码实现

使用步骤:

  1. 创建共享内存
  2. 将共享内存映射到虚拟地址空间
  3. 内存中进行数据操作实现进程间通信
  4. 使用完毕后解除映射关系,然后删除共享内存
    如果有进程依然与共享内存保持映射链接关系,那么共享内存将不会被立即删除,而是等最后一个映射断开后删除,在这期间,将拒绝其他进程映射

相关函数

shmget

功能:⽤来创建共享内存
原型
int shmget(key_t key, size_t size, int shmflg);
参数
key:这个共享内存段名字
size:共享内存⼤⼩
shmflg:由九个权限标志构成,它们的⽤法和创建⽂件时使⽤的mode模式标志是⼀样的
返回值:成功返回⼀个⾮负整数,即该共享内存段的标识码;失败返回-1

shmat

功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
shmid: 共享内存标识
shmaddr:指定连接的地址  可以设置为NULL
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY(要么只读要么读写)
返回值:成功返回⼀个指针,指向共享内存第⼀个节;失败返回-1

shmdt

功能:将共享内存段与当前进程脱离
原型
int shmdt(const void *shmaddr);
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

shmctl

功能:⽤于控制共享内存
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
			IPC_STAT:把shmid_ds中的数据设置成当前共享内存的当前关联值
			IPC_SET:在权限足够的情况下,将共享内存中的当前关联值设置成shmid_ds的数据
			IPC_RMID:删除共享内存(当然要等到没有进程映射这块内存时才删除)
buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

示例:

memshare.c

扫描二维码关注公众号,回复: 4215234 查看本文章
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  6 #include <sys/ipc.h>
  7 #include <sys/shm.h>
  8 
  9 #define IPC_KEY 0x12345678
 10 int main()
 11 {
 12     //1. 创建共享内存 13     //int shmget(key_t key, size_t size, int shmflg);
 14     //  key:   操作系统上ipc标识 15     //  size:  要创建的共享内存大小
 16     //  shmflg:
 17     //      IPC_CREAT|IPC_EXCL|0664
 18     //  返回值:操作句柄    失败:-1
 19     int shmid = -1;
 20     shmid = shmget(IPC_KEY, 32, IPC_CREAT|0664);
 21     if (shmid < 0) {
 22         perror("shmget error");
 23         return -1;
 24     }
 25     //2. 将共享内存映射到虚拟地址空间
 27     //  shmid:      操作句柄
 28     //  shmaddr:   映射起始地址,NULL(操作系统分配)
 31     void *shm_start = shmat(shmid, NULL, 0);
 32     if (shm_start == (void*)-1) {
 33         perror("shmat errro");
 34         return -1;
 35     }
 36     while(1) {
 37         //直接通过这个首地址操作共享内存即可
 38         printf("please input:");
 39         //清空一下共享内存中的数据
 40         memset(shm_start, 0x00, 32);
 41         scanf("%s", (char*)shm_start);
 42         sleep(1);
 43     }
 44     //4. 不玩了 a. 解除映射     b. 删除
 45     //解除映射
 46     //int shmdt(const void *shmaddr);
 47     //  shmaddr 共享内存的映射首地址
 48     //  返回值:成功:0     失败:-1
 49     shmdt(shm_start);
 50     //删除共享内存
 51     //int shmctl(int shmid, int cmd, struct shmid_ds *b    uf);
 52     //  shmid:  句柄
 53     //  cmd:   IPC_RMID    删除
 54     //  buf:   用于接收共享内存描述信息,不关心可以置空
 55     shmctl(shmid, IPC_RMID, NULL);
 56     return 0;
 57 }
 58 

memshare1.c

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  6 #include <sys/ipc.h>
  7 #include <sys/shm.h>
  8 
  9 #define IPC_KEY 0x12345678
 10 int main()
 11 {
 12     //1. 创建共享内存 13     //int shmget(key_t key, size_t size, int shmflg);
 14     //  key:   操作系统上ipc标识 15     //  size:  要创建的共享内存大小
 16     //  shmflg:
 17     //      IPC_CREAT|IPC_EXCL|0664
 18     //  返回值:操作句柄    失败:-1
 19     int shmid = -1;
 20     shmid = shmget(IPC_KEY, 32, IPC_CREAT|0664);
 21     if (shmid < 0) {
 22         perror("shmget error");
 23         return -1;
 24     }
 25     //2. 将共享内存映射到虚拟地址空间
 27     //  shmid:      操作句柄
 28     //  shmaddr:   映射起始地址,NULL(操作系统分配)
 29     //  shmflg:     SHM_RDONLY--只读    否则读写
 30     //  返回值:映射的虚拟地址空间首地址
 31     void *shm_start = shmat(shmid, NULL, 0);
 32     if (shm_start == (void*)-1) {
 33         perror("shmat errro");
 34         return -1;
 35     }
 36     while(1) {
 37         printf("%s\n", (char*)shm_start);
 38         sleep(1);
 39     }
 40     //4. 不玩了 a. 解除映射     b. 删除
 41     //解除映射
 42     //int shmdt(const void *shmaddr);
 43     //  shmaddr 共享内存的映射首地址
 44     //  返回值:成功:0     失败:-1
 45     shmdt(shm_start);
 46     //删除共享内存
 47     //int shmctl(int shmid, int cmd, struct shmid_ds *b    uf);
 48     //  shmid:  句柄
 49     //  cmd:   IPC_RMID    删除
 50     //  buf:   用于接收共享内存描述信息,不关心可以置空
 51     shmctl(shmid, IPC_RMID, NULL);
 52     return 0;
 53 }
 54 ```

猜你喜欢

转载自blog.csdn.net/Ferlan/article/details/84190808