Linux进程IPC浅析[进程间通信SystemV共享内存]

  • 共享内存概念,概述
  • 共享内存的相关函数

共享内存概念,概述

共享内存区域是被多个进程共享的一部分物理内存

多个进程都可把该共享内存映射到自己的虚拟内存空间,全部用户空间的进程若要操作共享内存。都要将其映射到自己的虚拟内存空间中。通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信

共享内存是进程间共享数据的一种最快的方法。一个进程向共享内存区域写入了数据。共享这个内存区域的全部进程就能够立马看到当中的内容

本身不提供同步机制,可通过信号量进行同步(用信号量进行通知)

提升数据处理效率。一种效率最高的IPC机制

共享内存的属性信息:

struct shmid_ds{
struct ipc_perm shm_perm;
size_t shm_segsz; //共享内存大小
pid_t shm_lpid; //最后一次调用系统调用的进程的pid
pid_t shm_cpid; //创建者pid
shmatt_t shm_nattch;//当前成功映射的进程的数量
time_t shm_atime; //最后一个成功映射的时间
time_t shm_dtime; //最后一个解除映射的时间
time_t shm_ctime; //最后一次改变的时间
....;
}

共享内存的使用步骤:

使用shmget函数创建共享内存
使用shmat函数映射共享内存。将这段创建的共享内存映射到详细的进程虚拟内存空间中

创建共享内存

#include<sys/shm.h>
int shmget(key_t key,size_t size,int shmflg);
返回:假设成功。返回内核中共享内存的表示ID,假设失败,则返回-1 參数:
key:用户制定的共享内存键值
size_t:共享内存的大小
shmflg:IPC_CREAT,IPC_EXCL等权限
errno:
EINVAL(无效的内存段)
EEXIST(内存段已经存在。无法创建)
EIDRM(内存段已经被删除)
ENOENT(内存段不存在)
EACCES(权限不够)
ENOMEN(没有足够的内存来创建内存段)

对共享内存的控制:

#include<sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
返回:成功返回0,出错返回-1
參数:
shmid:共享内存ID
buf:共享内存属性指针
cmd:
IPC_STAT 获取共享内存段属性
IPC_SET 设置共享内存段属性
IPC_RMID 删除共享内存段
SHM_LOCK 锁定共享内存段页面
SHM_UNLOCK 解除共享内存段页面的锁定

共享内存的映射和映射的解除:

#include<sys/shm.h>
void* shmat(int shmid,char *shmaddr,int shmflag);
返回:成功返回共享内存映射到进程虚拟内存空间中的地址。失败返回-1,然后通过操作共享内存的地址来进行写操作
int shmdt(char *shmaddr);
返回:假设失败,返回-1
參数:
shmid:共享内存ID
shmaddr:映射到进程虚拟内存空间的地址,建议设置为0,由系统分配
shmflg:若shmaddr设置为0,则shmflag也设置为0
SHM_RND
SHMLBA 地址为2的乘方
SHM_RDONLY 仅仅读方式链接
errno
EINVAL 无效的IPC ID值或者无效的地址
ENOMEN 没有足够内存
EACCESS 权限不够
子进程不继承父进程创建的共享内存,大家是共享的,子进程继承父进程映射的地址

下面的代码是通过管道的形式来对共享内存实现同步,一个进程实现对共享内存的写后,通过管道通知另外一个进程去从共享内存中去读取:

/*
* ===========================================================================
*
* Filename: tell.h
* Description:
* Version: 1.0
* Created: 2017年04月16日 10时40分31秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/ #ifndef __TELL_H_
#define __TELL_H_
//初始化管道
extern void pipe_init();
//通知管道
extern void pipe_notify();
//管道堵塞等待
extern void pipe_wait();
//销毁管道
extern void pipe_destory(); #endif
/*
* ===========================================================================
*
* Filename: tell.c
* Description:
* Version: 1.0
* Created: 2017年04月16日 10时42分23秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/ #include<stdio.h>
#include<stdlib.h>
#include"tell.h"
#include<unistd.h> #define BUFFER_SIZE 1024
//管道的文件描写叙述符号
static int pipe_fd[2]; //初始化管道
extern void pipe_init(){
if(pipe(pipe_fd) < 0){
perror("create pipe error\n");
}
} //管道等待
extern void pipe_wait(){
char buffer[BUFFER_SIZE];
if((read(pipe_fd[0],&buffer,sizeof(buffer))) != 0){
printf("read content:%s\n",buffer);
}
} //通知管道
extern void pipe_notify(){
ssize_t size;
char content[] = "notify";
if((size = write(pipe_fd[1],content,sizeof(content))) !=sizeof(content)){
perror("write error");
}
} //销毁管道
extern void pipe_destory(){
close(pipe_fd[0]);
close(pipe_fd[1]);
}
/*
* ===========================================================================
*
* Filename: shmtest.c
* Description:
* Version: 1.0
* Created: 2017年04月16日 10时51分54秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"tell.h"
#include<sys/shm.h> #define SHM_BUFFER_SIZE 1024
int main(int argc,char*argv[]){
pid_t pid;
int shmid;
//创建共享内存
shmid = shmget(IPC_PRIVATE,SHM_BUFFER_SIZE,IPC_CREAT | IPC_EXCL | 0777);
if(shmid < 0){
perror("create share memory error");
}
//初始化管道
pipe_init();
if((pid = fork()) < 0){ }else if(pid > 0){
//父进程运行的时间片
//父进程进行共享内存的映射
int* shm_int_pointer = shmat(shmid,0,0);
if(shm_int_pointer == (int *)-1){
perror("error");
}
//父进程往共享内存中写数据
*shm_int_pointer = 10;
*(shm_int_pointer + 1)= 100;
*(shm_int_pointer + 2) = 1000; //取消共享内存的映射
shmdt(shm_int_pointer);
//通知子进程
pipe_notify();
//管道进行销毁
pipe_destory();
wait(0);
}else{
//子进程运行的时间片
//子进程堵塞
pipe_wait();
int *shm_int_pointer = shmat(shmid,0,0);
if(shm_int_pointer == (int *)-1){
perror("error");
exit(1);
}
int num1 = *shm_int_pointer;
int num2 = *(shm_int_pointer+1);
int num3 = *(shm_int_pointer+2);
printf("num1:%d,num2:%d,num3:%d\n",num1,num2,num3); shmdt(shm_int_pointer);
//删除共享内存
int shm_ctl_result = shmctl(shmid,IPC_RMID,NULL);
if(shm_ctl_result == -1){
perror("delete shmctl error");
}
pipe_destory();
} return 0;
}

以上部分就是关于共享内存部分的相关简单的调用,代码调试过

欢迎持续訪问博客

Linux进程IPC浅析[进程间通信SystemV共享内存]的更多相关文章

  1. Linux进程通信之System V共享内存

    前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...

  2. linux进程间的通信之 共享内存

    一.共享内存介绍 共享内存是三个IPC(Inter-Process Communication)机制中的一个. 它允许两个不相关的进程访问同一个逻辑内存. 共享内存是在两个正在进行的进程之间传递数据的 ...

  3. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  4. Linux进程间通信(四) - 共享内存

    共享内存的优势 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只 ...

  5. linux进程间通信之共享内存篇

    本文是对http://www.cnblogs.com/andtt/articles/2136279.html中共享内存(上)的进一步阐释说说明 1 共享内存的实现原理 共享内存是linux进程间通讯的 ...

  6. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  7. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  8. linux内核剖析(十一)进程间通信之-共享内存Shared Memory

    共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程 ...

  9. Linux进程间通信——使用共享内存

    一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...

随机推荐

  1. django URL,views,html请求顺序

    进来的请求转入/hello/.   Django通过在ROOT_URLCONF配置来决定根URLconf.     Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目 ...

  2. vs2008控件查看器

    使用 OLE/COM 对象查看器 通过读取控件的类型库,OLE/COM 对象查看器使您得以查看控件的接口. 使用 OLE/COM 对象查看器 单击“工具”菜单上的“OLE/COM 对象查看器”或在命令 ...

  3. SQL使用exists时的多种写法

    from test; go from test; go 下面这种效率明显高不少.

  4. 使用jave2将音频wav转换成mp3格式

    最近需要用到语音合成功能,网上查阅了一番,发现可以使用腾讯云的语音合成API来完成这个功能,但是腾讯云的api返回的是wav格式的音频文件,这个格式的文件有些不通用,因此需要转换成mp3格式的文件.  ...

  5. git 设置ss代理

    git config --global https.proxy http://127.0.0.1:1080       git config --global https.proxy https:// ...

  6. hdu5126 stars

    题目描述 题解: 和二维的比起来差不多. 但是这是四维偏序. 所以搞一下CDQ套CDQ. CDQ是维度a已经有序,按维度b排序,然后将维度c存入一维数据结构. 所以我们在第一层CDQ中分治处理,将合法 ...

  7. MariaDB数据库(一)

    1.数据库简介 1.1 什么是数据库? 简单的说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构(数据结构是指数据的组织形式或数据之间的联系)来组织,存储的,我们可以通过数据库提供的多种方 ...

  8. (二十三)Python 3 文件操作

    文件处理流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 打开文件的模式有三种: 只读模式(默认) 只写模式(不可读,不存在则创建,存在则覆盖) 追加模式(可读,不存在则 ...

  9. python基础002

    1.pycharm安装与添加解释器 专业版.英文界面,不要汉化—一定要尊重知识产权 算术运算符:+ - * / // % ** ^ 布尔运算符:== > < >= <= 逻辑运 ...

  10. Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现

    前言 开心一刻 小明:“妈,我被公司开除了”,妈:“啊,为什么呀?”, 小明:“我骂董事长是笨蛋,公司召开高层会议还要起诉我”,妈:“告你诽谤是吧?”,小明:“不是,他们说要告我泄露公司机密” Bea ...