【Linux操作系统】--System V的共享内存进程通信

目录

System V起源

共享内存原理

共享内存应用原理

共享内存接口

创建共享内存shmget

shmget测试 

 创建和删除代码

挂载接口shmat

 去关联调用接口shmdt

 第二个进程与共享内存挂载

两个进程进行通信

共享内存的特性

补充知识

【shmget的第二个参数size】

 shmid每次运行的数量会增加问题

system V信号量(非重点)


System V起源

进程间通信除了通过管道,都是基于文件的通信方式,还有一种方式是:SystemV标准的进程间通信方式。SystemV是一个在OS层面专门为进程通信设计的一个方案。这些都是由计算机科学家和程序员设计的,并且需要给用户使用。

如果要给用户用,是以什么方式给用户使用的呢?在操作系统层面上,SystemV是OS内核的一部分,是为OS中多进程提供的一种通信方案。但是OS不相信任何用户,给用户提供功能的时候,采用系统调用。所以System V进程间通信,一定会存在专门用来通信的接口:system call。

因为在早期由很多的方案,但是我们需要统一使用一个方案,所以现在诞生了在统一主机内的进程间通信方案:system V方案。

进程间通信的本质就是:让不同的进程看到同一份资源。

  • 共享内存
  • 消息队列
  • 信号量

共享内存原理

A和B两个进程互相独立,物理内存当中代码和数据也互相独立,所以两个进程不会互相干扰,这就是两个进程具有独立性。

现在我们要进行进程间通信,我们要在物理内存当中要创建一个内存块。但是实际可能并不是这么操作,要根据当前内存使用情况来具体操作,我们现在这么理解。

第二部就是要通过某种调用,让进程”挂接“到这份内存空间上。什么是挂接到内存?我们已经有了一块内存空间,并且地址空间中有很大一批没有使用的物理地址空间,页表也有很多没有被填写的映射关系,所以通过某种系统调用,把刚刚这个内存空间通过页表映射到地址空间中。所以我们在地址空间中就能拿到这个内存空间的起始地址。那么A和B进程都一样,第一步创建的内存块通过页表映射,都挂接到了各自地址空间中。让参与通信的多个进程挂接到同一份内存上,此时达到了让不同进程看到了同一份资源,这种通信方案叫做共享内存

1.通过某种调用,在内存中创建一份内存空间。

2.通过某种调用,让进程”挂接“到这份内存空间上。

在后面可能不会共享内存了。所以在不用共享内存的时候

3.去关联(去挂接)

4.释放共享内存

综上共享内存的接口有4个,当然这四个是核心接口。

共享内存应用原理

OS内可能存在多个进程同时使用不同的共享内存来进行进程间通信。OS不可能只对一组共享内存通信,所以共享内存在系统中可能存在多份。因为存在多份共享内存,所以操作系统要对这些共享内存进行管理。那么如何管理呢?就是先描述,再组织。这里先描述就是对共享内存一系列属性的描述,它放在描述共享内存属性的结构体里,比如共享内存什么时候创建,在哪创建,有多大,通信的是哪两个进程等等。共享内存有多个,那么将共享内存的数据结构以链表形式储存起来,最终对共享内存的管理变成了对链表的增删查改,这个就是再组织。

那我们怎么保证,两个或多个进程,看到的是同一个共享内存呢?在命名管道中,当读端将管道创建好后,写端通过路径+文件名来获取这个管道达到双方通信。所以类比于此,共享内存一定要有一定的标识唯一性的ID,方便让不同的进程能识别同一个共享内存资源!

那么这个ID应该在哪里?当我们要找一个进程的时候,是要找对应进程的PID,而进程的PID是放在描述进程属性结构的PCB块中的。那么共享内存的ID也是放在描述共享内存属性的结构体中的。

共享内存接口

创建共享内存shmget

SYNOPSIS
       #include <sys/ipc.h>
       #include <sys/shm.h>

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

第一个参数key是通过ftok设置,具体在下面。

第二个参数size是创建共享内存的大小,这个大小建议是4KB的整数倍。

第三个参数有两种选项,为当中给出说明:

  • 如果单独使用IPC_CREAT,或者shmflg为0,不存在共享内存则创建一个共享内存,如果创建的共享内存已经存在,则直接返回当前已经存在的共享内存,这种设置基本不会空手而归。
  • IPC_EXCL单独使用是没有意义的。需要跟IPC_CREAT一起使用。IPC_CREAT|IPC_EXCL:如果不存在共享内存,则创建它;如果已经有了共享内存,则返回出错。它的意义是:如果调用成功,得到的一定是一个最新的,没有被别人使用的共享内存!

那么它的返回值:如果创建失败返回-1;如果返回成功,就会返回标识共享内存的一个数字,这个数字就是我们上面提到的,让不同进程看到同一份资源的共享内存ID,那么这个ID是要用户自己设定的。理论上这个ID设置多少都可以,只要让两个不同进程看到这个数字就可以,具体是几不重要,重要的是它和别人不一样。所以我们要通过一个函数ftok来设置这个具体的ID。

【ftok】

ftok第一个参数是自定义路径名,第二个参数是自定义的项目ID。最后唯一的共享内存ID就是通过路径名+项目ID来标识。ftok创建也有可能失败,如果失败了那么返回-1。而最后ftok最后生成的返回值并不重要,只要它能生成一个值来唯一标识这块共享内存就可以。最后shmget接口通过ftok生成的key值会设置进内核的关于sh在内核中的数据结构,就是描述共享内存的属性结构体,这个我们在上面也有提到。

shmget测试 

我们创建两个.c文件和一个.h文件,.h用来放置.c的公共内容,两个.c文件用来进行通信。然后将他的makefile文件也写出来,然后直接用make编译。

[wjy@VM-24-9-centos shared_memory]$ touch client.c
[wjy@VM-24-9-centos shared_memory]$ touch server.c
[wjy@VM-24-9-centos shared_memory]$ touch comm.h
[wjy@VM-24-9-centos shared_memory]$ cat makefile
.PHONY:all
all:client server 

client:client.c
	gcc -o $@ $^
server:server.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f client server fifo

comm.h文件中我们将ftok中的路径名和自定义项目ID用宏创建出来,这样在ftok传参数的时候传宏就可以。

[wjy@VM-24-9-centos shared_memory]$ cat comm.h
#pragma once 

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATH_NAME ./
#define PROG_ID 0X6666

【创建ID】

在server.c中我们写一个代码来看一下这个ftok最后创建出来用来标识共享内存的返回值是多少。最后这个1711348774就是最后共享内存的标识ID。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值