博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux进程IPC浅析[进程间通信SystemV共享内存]
阅读量:3749 次
发布时间:2019-05-22

本文共 5001 字,大约阅读时间需要 16 分钟。

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
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
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
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
#include
#include"tell.h"#include
#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
#include
#include
#include
#include"tell.h"#include
#define SHM_BUFFER_SIZE 1024int 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;}

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

转载地址:http://izbsn.baihongyu.com/

你可能感兴趣的文章
Ubuntu基础常用命令(03)——关机重启、vi 完~
查看>>
输入\数据转换类型\运算符\判断语句
查看>>
多任务(进程线程)
查看>>
超易懂的MySQL缓存机制
查看>>
mysql-Explain
查看>>
mysql-事务
查看>>
C语言排序算法
查看>>
python常用模块整理(超详细)
查看>>
用nginx做反向代理
查看>>
史上最易部署lvs集群-tun模式
查看>>
python进程,线程,协程
查看>>
python网络编程
查看>>
你值得拥有的linux下的网络io 同步/异步/阻塞/非阻塞/BIO/NIO/AIO
查看>>
nginx日志文件配置
查看>>
HTTP over SSL/TLS
查看>>
CentOS安装fortune+cowsay
查看>>
用vue创建一个项目
查看>>
$listeners与.native的使用
查看>>
熟悉Linux 下静态库.a 与.so 库文件的生成与使用——实例
查看>>
算法训练 1的个数(输入正整数n,判断从1到n之中,数字1一共要出现几次。例如1123这个数,则出现了两次1。例如15,那么从1到15之中,一共出现了8个1。)
查看>>