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

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;
}

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

欢迎持续访问博客

时间: 2024-10-11 15:13:15

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

linux进程间的通信(C): 共享内存

一.共享内存介绍 共享内存是三个IPC(Inter-Process Communication)机制中的一个. 它允许两个不相关的进程访问同一个逻辑内存. 共享内存是在两个正在进行的进程之间传递数据的一种非常有效的方式. 大多数的共享内存的实现, 都把由不同进程之间共享的内存安排为同一段物理内存. 共享内存是由IPC为进程创建一个特殊的地址范围, 它将出现在该进程的地址空间中. 其他进程可以将同一段共享内存连接它们自己的地址空间中. 所有进程都可以访问共享内存中的地址, 就好像它们是由mallo

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

一.共享内存介绍 共享内存是三个IPC(Inter-Process Communication)机制中的一个. 它允许两个不相关的进程访问同一个逻辑内存. 共享内存是在两个正在进行的进程之间传递数据的一种非常有效的方式. 大多数的共享内存的实现, 都把由不同进程之间共享的内存安排为同一段物理内存. 共享内存是由IPC为进程创建一个特殊的地址范围, 它将出现在该进程的地址空间中. 其他进程可以将同一段共享内存连接它们自己的地址空间中. 所有进程都可以访问共享内存中的地址, 就好像它们是由mallo

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

Linux环境进程间通信:共享内存

共享内存简介 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC.共享内存的方式有两种:mmap()系统调用和系统V共享内存. mmap()系统调用 mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存.普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作. 注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的.它本身提供了不同于一般对普

Linux系统编程——进程间通信:共享内存

概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 共享内存的特点: 1)共享内存是进程间共享数据的一种最快的方法. 一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 2)使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥. 若一个进程正在向共享内存区写数据,则在它做

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

下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共

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

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

进程间通信(9) - 共享内存(System V)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.介绍 共享内存也是一种IPC,它是目前最快的IPC,它的使用方式是将同一个内存区映射到共享它的不同进程的地址空间中,这样这些进程间的通信就不再需要通过内核,只需对该共享的内存区域进程操作就可以了. 共享内存与其他的进程间通信最大的优点是:数据的复制只有两次,一次是从输入文件到共享内存区,一次从共享内存区到输出文件.而其他的则是需要复制4次:服务器将输入文件读入自己的进

深入理解进程间通信之共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.是针对其他通信机制运行效率较低而设计的.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共