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. mysql数据库比较,各数据库不同之处

    和mysql数据库比较,各数据库不同之处: Oracle数据库:字段类型不同 postgresql数据库:show tables不同; SQL语句需要前面加上 模式名 Mongodb数据库:文档存储, ...

  2. sublime中项目无法添加文件夹

    问题记录 mac中,使用vue init webpack project 后,在sublime中打开,但是添加新文件夹和删除,总提示没有权限, 然后用git提交吧 也不行,每次都要sudo 出现的提示 ...

  3. Node.js 创建server服务器

    var http=require('http'); //引入http模块 var server=http.createServer(function(req,res){  //创建一个server r ...

  4. 退役选手ZlycerQan的强大的的高精度

    #include <cstdio> #include <iostream> #include <vector> #include <iomanip> # ...

  5. 计算机网络之TCP拥塞控制

    1. 首先,拥塞控制和流量控制是不一样的. 拥塞控制是防止过多的数据注入到网络中,可以使网络中的路由器或链路不致过载,是一个全局性的过程.  流量控制是点对点通信量的控制,是一个端到端的问题,主要就是 ...

  6. 【模板】插头dp

    题目描述 题解: 插头$dp$中经典的回路问题. 首先了解一下插头. 一个格子,上下左右四条边对应四个插头.就像这样: 四个插头. 一个完整的哈密顿回路,经过的格子一定用且仅用了两个插头. 所以所有被 ...

  7. PHP中的正则

    概述 正则表达式是一种描述字符串结果的语法规则,是一个特定的格式化模式,可以匹配.替换.截取匹配的字符串. j简单的说就是通过一些规定的符号和字符组合成的一种语法规则 其实,只有了解一种语言的正则使用 ...

  8. python:端口扫描邮件推送

    #!/usr/bin/env python import pickle import smtplib from email.mime.text import MIMEText import nmap ...

  9. Java中线程的使用

    多线程的创建及启动 一.继承Thread类创建线程子类 1.在这子类中重写run方法,在run方法内写线程任务代码 2.创建该子类实例,即是创建了一个线程实例 3.调用该实例的start方法来启动该线 ...

  10. Device eth0 does not seem to be present,delaying initialization问题

    1.打开/etc/udev/rules.d/70-persistent-net.rules: cat /etc/udev/rules.d/70-persistent-net.rules 文件内容如图: ...