Linux操作系统:进程间通信(一)共享存储

共享内存


共享内存指 (shared memory,shm)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。
任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。
共享内存通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。

在这里插入图片描述

C/S模式数据传递只复制两次:
(1)输入文件到共享内存
(2)共享内存到输出文件

在这里插入图片描述

特点:
(1)共享内存是最快的IPC方式,进程间的数据传递不再涉及内核
(共享内存中的单个数据副本,对共享该内存区的所有线程和进程都是共有的)
(2)fork()之后,父子进程之间并不共享数据
(3)各个进程都能够共同访问的共享的内存区域;是独立于所有的进程空间之外的地址区域;

(不相关)进程之间的通信
进程对于共享内存的操作与管理主要是:
(1)、申请创建一个共享内存区域(操作系统内核是不可能主动为进程创建共享内存的),操作系统内核得到申请然后创建
(2)、申请使用一个已存在的共享内存区域
(3)、申请释放共享内存区域(操作系统内核也是不可能主动释放共享内存区域的),操作系统内核得到申请然后释放
说明key_t key

建立映射mmap

在这里插入图片描述
建立内存区映射

#include <sys/mman.h>

void mmap(void addr,size_t len,int prot,int flags,int fd,off_t offset);

//返回: sus 则为映射区的起始地址 ,error 则为map_failed

解除某个进程地址空间的映射关系

#include <sys/mman.h>

int munmap(void * addr,size_t len);

//返回: sus 则为0 ,error 则为-1

同步硬盘文件内容与内存映射区的 内容

#include <sys/mman.h>

int msync(void * addr,size_t len ,int flags);

//返回: sus 则为0 ,error 则为-1

Posix共享内存

#include <sys/ipc.h>

#include <sys/shm.h>

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

功能:

创建或打开一块共享内存区。

参数:

key:进程间通信键值,ftok() 的返回值。

size:该共享存储段的长度(字节)。

shmflg:标识函数的行为及共享内存的权限,其取值如下:

IPC_CREAT:如果不存在就创建

IPC_EXCL: 如果已经存在则返回失败

位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式和 open() 函数的 mode_t 一样(open() 的使用请点此链接),但可执行权限未使用。

返回值:

成功:共享内存标识符。

失败:-1。

所需头文件:

#include <sys/types.h>

#include <sys/shm.h>

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

功能:

将一个共享内存段映射到调用进程的数据段中。简单来理解,让进程和共享内存建立一种联系,让进程某个指针指向此共享内存。

参数:

shmid:共享内存标识符,shmget() 的返回值。

shmaddr:共享内存映射地址(若为 NULL 则由系统自动指定),推荐使用 NULL。

shmflg:共享内存段的访问权限和映射条件( 通常为 0 ),具体取值如下:

0:共享内存具有可读可写权限。

SHM_RDONLY:只读。

SHM_RND:(shmaddr 非空时才有效)

返回值:

成功:共享内存段映射地址( 相当于这个指针就指向此共享内存 )

失败:-1

#include <sys/types.h>

#include <sys/shm.h>

int shmdt(const void *shmaddr);

功能:

将共享内存和当前进程分离( 仅仅是断开联系并不删除共享内存,相当于让之前的指向此共享内存的指针,不再指向)。

参数:

shmaddr:共享内存映射地址。

返回值:

成功:0

失败:-1

#include <sys/ipc.h>

#include <sys/shm.h>

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

功能:

共享内存属性的控制。

参数:

shmid:共享内存标识符。

cmd:函数功能的控制,其取值如下:

IPC_RMID:删除。(常用 )

IPC_SET:设置 shmid_ds 参数,相当于把共享内存原来的属性值替换为 buf 里的属性值。

IPC_STAT:保存 shmid_ds 参数,把共享内存原来的属性值备份到 buf 里。

SHM_LOCK:锁定共享内存段( 超级用户 )。

SHM_UNLOCK:解锁共享内存段。

SHM_LOCK 用于锁定内存,禁止内存交换。并不代表共享内存被锁定后禁止其它进程访问。其真正的意义是:被锁定的内存不允许被交换到虚拟内存中。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能。

buf:shmid_ds 数据类型的地址(具体类型请点此链接 ),用来存放或修改共享内存的属性。

返回值:

成功:0

失败:-1

System V共享内存

说明:

关于共享内存使用

共享内存使用:
(1)、建立进程与共享内存的映射关系
(2)、读/写(直接使用指针即可
(3)、如果对于共享内存的使用结束,此时就要断开与共享内存的映射
对于第一步来说,需要使用的API:shmat()方法。
对于第三步来说,需要使用的API:shmdt()方法。
被映射正在使用共享内存是否此时可以执行删除操作呢
是,虽然可以执行删除操作,却不能将其直接删除掉。而是做了2个操作
(1)、将其状态置为dest(可回收状态)
(2)、将其key值置为0x00000000,IPC_PRIVATE值

当共享内存处于dest(待回收状态),则将其资源设为"私有"(只能将该共享资源分享给其子进程,其它进程无法创建于该资源的使用),当所有的使用该共享内存的进程都退出,此时操作系统才回收共享内存
共享内存的控制
共享内存的控制信息可以通过shmctl()方法获取,
API:int shmctl(int shmid, int cmd, struct shmid_ds *buf)
会保存在struct_shmid_ds结构体中
共享内存的控制主要是shmid_ds,即就是共享内存的控制信息
cmd:看执行什么操作(1、获取共享内存信息;2、设置共享内存信息;3、删除共享内存)

关于key_t

(1)、key_t是一个long类型,是IPC资源外部约定的key(关键)值,通过key值映射对应的唯一存在的某一个IPC资源
(2)、通过key_t的值就能够判断某一个对应的共享内存区域在哪,是否已经创建等等。
(3)、一个key值只能映射一个共享内存区域,但同时还可以映射一个信号量,而且还能同时映射一个消息队列资源,于是就可以使用一个key值管理三种不同的资源
int shmget(key_t key, size_t size, int shmflg); //返回值是共享内存的标号shmid
int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0755);

key_t值的产生,有两种方式:
(1)、把key值写死; // 任意指定一个数字
(2)、根据文件的inode编号生成。需要调用的API:ftok("./tmp/a.c", 3)方法,该方法是获取指定文件的inode编号在根据第二个参数计算得到最终的一个整型量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值