夜间模式暗黑模式
字体
阴影
滤镜
圆角
主题色
OS实验–利用Linux的共享内存通信机制实现两个进程间的通信
本文最后更新于 109 天前,其中的信息可能已经有所发展或是发生改变。

0x00 实验思路

简述:

  • 创建一个通讯通道,并且用IPC键值来标识这个通道,使得两个进程能够使用同一个通道进行通信。
  • 创建并初始化三个有名信号量 mutex receiver_response sender_write,对接受和发送过程上锁,避免读者写者冲突。
  • 通信双方通过共享内存首地址的值来判断是否已经发送或接受到消息
  • 发送方将发送的消息存入共享内存,接收方则不断轮询共享内存,以接受数据。
  • 进程结束后,销毁信号量与共享内存。

流程图如下

image-20200426224429743

0x01 知识点学习

ftok函数

函数ftok把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为

IPC(Inter-Process Communication 进程间通信) 键值,

也称IPC key键值:

进程间通信(IPC)
有两个东西可以标识一个IPC结构:标识符(ID)和键(key)。

键值(ID)
ID是IPC结构的内部名,用来确保使用同一个通讯通道(比如说这个通讯通道就是消息队列)。内部即在进程内部使用,这样的标识方法是不能支持进程间通信的。

标识符(key)
key就是IPC结构的外部名。当多个进程,针对同一个key调用get函数(msgget等),这些进程得到的ID其实是标识了同一个IPC结构。多个进程间就可以通过这个IPC结构通信。

ftok函数原型及说明如下:

所需头文件#include #include
函数说明把从pathname导出的信息与id的低序8位组合成一个整数IPC键
函数原型key_t ftok(const char *pathname, int proj_id)
函数传入值pathname:指定的文件,此文件必须存在且可存取
proj_id:计划代号(project ID)
函数返回值成功:返回key_t值(即IPC 键值)
出错:-1,错误原因存于error中
附加说明key_t一般为32位的int型的重定义

通过ftok返回的是根据文件(pathname)信息和计划编号(proj_id)合成的IPC key键值,从而避免用户使用key值的冲突。proj_id值的意义让一个文件也能生成多个IPC key键值。ftok利用同一文件最多可得到IPC key键值0xff(即256)个,因为ftok只取proj_id值二进制的后8位,即16进制的后两位与文件信息合成IPC key键值

信号量

有名信号量与无名信号量

有名信号量和无名信号量的差异在于创建和销毁的形式上,但是其他工作一样。

无名信号量只能存在于内存中,要求使用信号量的进程必须能访问信号量所在的这一块内存,所以无名信号量只能应用在同一进程内的线程之间(共享进程的内存),或者不同进程中已经映射相同内存内容到它们的地址空间中的线程(即信号量所在内存被通信的进程共享)。意思是说无名信号量只能通过共享内存访问。

相反,有名信号量可以通过名字访问,因此可以被任何知道它们名字的进程中的线程使用。

无论是有名信号量还是无名信号量,都可以通过以下函数进行信号量值操作:

wait

wait 为信号量值减一操作,总共有三个函数,函数原型如下:

post

post 为信号量值加一操作,函数原型如下:

有名信号量的创建

有名信号量创建可以调用 sem_open 函数,函数说明如下:

有名信号量的销毁

可以使用 sem_unlink 函数销毁一个有名信号量。函数说明如下:

共享内存的使用

shmget()函数

第一个参数,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget()函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.

不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用shmget()函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget()函数的返回值),只有shmget()函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。

第二个参数,size以字节为单位指定需要共享的内存容量

第三个参数,shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。

shmat()函数

第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。

它的原型如下:

第一个参数,shm_id是由shmget()函数返回的共享内存标识。

第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。

第三个参数,shm_flg是一组标志位,通常为0

调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.

0x02 实验代码

sender.c

receiver.c

0x03 测试结果

image-20200427225857643
暂无评论

发送评论 编辑评论


				
上一篇
下一篇