Unix-IPC之共享内存

一,共享内存的概念

共享内存通信技术是一种最快的可用IPC形式,它是针对其他通信机制运行效率低和设计的新型通信技术(其他的如:信号量,管道,套接字等)。这种通信技术往往与其他通信机制(如信号量)结合使用,用于达到进程间的同步及互斥。

原理:

这种方式是在所有进程的独立空间之外开辟一块内存空间,它不属于任何一个进程,当所有进程都可以访问。利用这样的共享特性,发送进程就可以往共享区域中写入数据,而接收进程则可以从共享区域中获取所需信息。

采用共享内存的进程通信的特点:

  • 进程通信中,需要交互的数据或消息不发生存储移动。
  • 当需要交互时,通信进程双方通过共享内存区域完成信息交互。
  • 对于共享内存区,可以用虚拟映射方式将其作为交互进程的内存使用。

二,相关系统调用

共享内存区的建立

Unix中通系统调用shmget()来建立一块共享内存,函数定义:

int shmget(key_t key, int size, int flag);

参数说明:

  • key:表示共享内存的标识符
  • size:共享内存以字节为单位的最小值,如果创建的是一个新共享区必须指定size,若使用已有的共享内存则size指定为0
  • flag:是构成共享区标识的参照值
  • 返回值:若要建立的共享区(传入的标识符)已存在,返回共享区描述符shmid,若不存在则先建立共享区在返回描述符

共享区的操作

Unix中使用shmctl系统调用查询共享区的状态信息,如大小、所链接的进程数、创建者标识符等。也可以修改其属性,还可以用来对共享区进行加锁或解锁。函数定义:

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

参数说明

  • shmid:是共享区的标识符
  • cmd:表明在shmid指定的存储区可以执行以下命令:

IPC_STAT 对此段取shmid_ds结构存放在buf指向的结构中

IPC_SET 按buf指向的结构中的值设置此段相关的三个字段

IPC_RMID 从系统中删除该共享区

SHM_LOCK 对该共享区进行锁定,此命令只能有超级用户使用

SHM_UNLOCK 解锁该共享区,此命令只能由超级用户使用

共享区的链接

一但建立了共享区或获得了一个已有共享区的描述符后,就可以利用系统调用将该共享区链接到用户指定的某个进程的虚拟地址shmaddr上,并指定该存储区的访问属性(只读,还是可读可写)。此后进程就可以像对其他虚拟地址一样来访问该存储区。函数定义:

void *shmat(int shmid, void *addr, int flag);

共享区链接到调用进程的哪个地址上与调用函数中的addr参数和在flag中是否指定SHM_RND位有关:

  • addr为0,此段链接由内核选择的第一个可用地址上
  • addr非0,且未指定SHM_RND,此段链接到addr所指定的地址上
  • addr非0,且指定了SHM_RND,此段链接到(addr-(addr mod SHMLBA))所表示的地址上

进程和共享区断开

当进程不需要共享内存时,可以利用系统调用shmdt()把该区与进程断开。但是shmdt()函数并不会删除共享区。

int shmdt(void *addr);

这里参数addr是shmat()调用的返回值。


三,实验

实验思路就是先在主进程中创建共享区并写入数据,再利用fork()系统调用创建一个子进程,子进程链接上共享区从中读取数据。代码如下:

//3 head file about share memory
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
//head file about process : fork() wait()
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h> #define SHM_MODE (SHM_R | SHM_W)
#define SHM_SIZE 2048
#define MSG "Hello, son process!" int main(){ int segment_id;
char *shared_memory;
pid_t pid; //creat share memory
if( (segment_id=shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE))<0 ) perror("shmget error!\n"); //main process link to share memory
if( (shared_memory=shmat(segment_id, 0, 0)) == (void *)-1 ) perror("shmat error!\n"); //man process send the mesg
sprintf(shared_memory, MSG);
printf("main process send message:%s\n",&MSG); //man process unlink to share memory
shmdt(shared_memory); pid=fork(); if(pid<0){
perror("fork error:");
}
else if(pid==0){
printf("I am son process!\n"); if( (shared_memory=shmat(segment_id, 0, 0)) == (void *)-1 ) perror("shmat error!\n"); printf("son process get the message:%s\n",shared_memory); shmdt(shared_memory);
}
else{
printf("I am main process!\n"); wait(NULL);
shmctl(segment_id, IPC_RMID, 0);
} return 0;
}

输出结果:

main process send message:Hello, son process!

I am main process!

I am son process!

son process get the message:Hello, son process!

最新文章

  1. spring事务概念理解
  2. cors解决webapi post时报错405 method not allowed
  3. 直接请求json文件爬取天眼查企业信息(未解决验证码问题)——python3实现
  4. Lua与C的交互
  5. 一些站点使用的服务器软件、js 框架大收集 [ 整理中 ]
  6. zkclient
  7. 比callback更简洁的链式执行promise
  8. Xaml于string(弦)定义常量和处理空间
  9. 简单VR照片 使用陀螺仪、姿态角(Roll、Pitch、Yaw )、四元数
  10. Dynamics CRM2013 用户进入系统所必需的那些权限
  11. Markdown编辑技巧
  12. Mybatis中的逆向工程
  13. sql 随机获取数据
  14. aggregate基础 使用记录
  15. VM下安装Kali虚拟机
  16. Python笔记(二)查找重复元素
  17. vs2010补丁
  18. facebook api之Business Manager API
  19. MapGIS计算瓦片数据集
  20. [Week17] 个人阅读作业

热门文章

  1. shell-的特殊变量-难点理论
  2. CyclicBarrier原来是这样的
  3. python中的对文件的读写
  4. MeteoInfoLab脚本示例:TRMM 2A12 HDF数据
  5. day40 Pyhton 并发编程03
  6. CVE-2010-2883-CoolType.dll缓冲区溢出漏洞分析
  7. IE下文件上传, SCRIPT5: 拒绝访问 问题
  8. docker设置http访问
  9. centos8安装redis
  10. 视频和音频的 DOM