简介

共享内存(shared memory)是最简单的Linux进程间通信方式之一。使用共享内存,不同进程可以对同一块内存进行读写。由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝,所以,这种方式是效率最高、速度最快的进程间通信方式。

这种最大限度的自由也给共享内存带来了缺点:内核并不提供任何对共享内存访问的同步机制,比如同时对共享内存的相同地址进行写操作,则后写的数据会覆盖之前的数据。所以,使用共享内存一般还需要使用其他IPC机制(如信号量)进行读写同步与互斥。

基本原理

了解Linux内存管理机制,就很容易知道共享内存的原理了。大家知道,内核对内存的管理是以页(page)为单位的,Linux下一般一个page大小是4k。而程序本身的虚拟地址空间是线性的,所以内核管理了进程从虚拟地址空间到起对应的页的映射。创建共享内存空间后,内核将不同进程虚拟地址的映射到同一个页面:所以在不同进程中,对共享内存所在的内存地址的访问最终都被映射到同一页面。下图演示了共享内存的工作机制:

使用方法

共享内存的使用过程可分为 创建->连接->使用->分离->销毁 这几步。

共享内存的创建使用shmget函数(SHared Memory GET)函数,使用方法如下:

int segment_id = shmget (shm_key, getpagesize (),IPC_CREAT | S_IRUSR | S_IWUSER);

shmget根据shm_key创建一个大小为page_size的共享内存空间,参数3是一系列的创建参数。如果shm_key已经创建,使用该shm_key会返回可以连接到该以创建共享内存的id。

创建后,为了使共享内存可以被当前进程使用,必须紧接着进行连接操作。使用函数shmat(SHared Memory ATtach),参数传入通过shmget返回的共享内存id即可:

shared_memory = (char*) shmat (segment_id, 0, 0);

shmat返回映射到进程虚拟地址空间的地址指针,这样进程就能像访问一块普通的内存缓冲一样访问共享内存。例子中后两个参数我们全部传入0,采用默认的连接方式。实际上,第二个参数是希望连接的进程虚拟地址空间的地址,如果使用0,Linux会自己选用一个合适的地址;第三个参数是连接选项,可以是:

SHM_RND:将第二个参数指向的内存空间自动提升到page size的整数倍,如果不知明该参数,你需要自己控制第二个参数所指内存空间的大小。

SHM_RDONLY:该共享内存是只读的,不可写。

当共享内存使用完毕后,使用函数shmdt (SHared Memory DeTach)进行解连接。该函数以shmat返回的内存地址作为参数。每最后一个使用该共享内存的进程分离该共享内存后,内核将会对该共享内存自动销毁。当然,我们最好能显式的进行销毁,以避免不必要的共享内存资源浪费。 函数shmctl (SHared Memory ConTroL)可以返回共享内存的信息并对其进行控制,如

shmctl (segment_id, IPC_STAT, &shmbuffer);

可以返回该共享内存的信息,并将信息保存在第三个参数指向的shmid_ds结构体中。

当向第二个参数传入IPC_RMID时,共享内存将会在最后一个使用该共享内存的进程分离共享内存是销毁共享内存。

shmctl还有很多其他使用方法, 不再赘述。

示例程序

下面的示例程序,a进程每一秒的向共享内存写入一个随机数,b进程每隔一秒从该共享内存读出该数。

/*

* a.c

* write a random number between 0 and 999 to the shm every 1 second

*/

#include

#include

#include

#include

#include

int main(){

int shm_id;

int *share;

int num;

srand(time(NULL));

shm_id = shmget (1234, getpagesize(), IPC_CREAT);

if(shm_id == -1){

perror("shmget()");

}

share = (int *)shmat(shm_id, 0, 0);

while(1){

num = random() % 1000;

*share = num;

printf("write a random number %d\n", num);

sleep(1);

}

return 0;

}

/*

* b.c

* read from the shm every 1 second

*/

#include

#include

#include

#include

#include

int main(){

int shm_id;

int *share;

shm_id = shmget (1234, getpagesize(), IPC_CREAT);

if(shm_id == -1){

perror("shmget()");

}

share = (int *)shmat(shm_id, 0, 0);

while(1){

sleep(1);

printf("%d\n", *share);

}

return 0;

}

分别运行程序a和程序b,结果如下

PS

前面已经提到过,共享内存简单而高效,但是缺乏同步机制,所以,一般情况下需要配合其他IPC机制共同使用。否则肯定会带来同步问题。

linux ipc shmget 例子,Linux IPC之共享内存C 事例(示例代码)相关推荐

  1. Linux的IPC机制(一):共享内存

    0. 共享内存 比喻 本质 多个进程访问同一个逻辑内存 直接访问内存,不用read()/write()非常方便 1. POSIX 共享内存 资料:unpv22e-ch13 查看: man shm_ov ...

  2. Linux进程间通信(管道、消息队列、共享内存、信号、信号量)

    目录 Linux进程间通信概述 1.管道 无名管道(pipe) 有名管道(fifo) 2.消息队列(msg) 消息队列的通信原理 消息队列相关api 消息队列收发数据 键值生成 消息队列移除 3.共享 ...

  3. Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结

    Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...

  4. 进程间通信方式(三)-- IPC对象(消息队列、共享内存、信号灯集)

    IPC对象 1. IPC对象 2. 查看IPC对象命令 3. 消息队列 3.1 概念 3.2 相关函数 3.2.1 msgget() 创建或者打开消息队列 3.2.2 ftok() 获取键值 3.2. ...

  5. linux篇【9】:进程间通信(共享内存)——<后序>

    目录 一.system V共享内存--先让不同的进程看到同一份资源 1.共享内存原理 监控共享内存脚本 2.创建/获取 共享内存接口-shmget函数(shared memory get) 3.参数k ...

  6. Linux系统编程28:进程间通信之共享内存和相关通信接口(ftok,shmget,shmctl,shmat,shmdt)

    文章目录 (1)管道和共享内存的区别 (2)先组织,再描述 (3)进程间通信相关接口 A:ftok(获取唯一标识码) B:shmget(创建共享内存) C:shmctl(控制共享内存) D:shmat ...

  7. Linux进程间通信一 System V 共享内存简介与示例

    目录 1. System V共享内存简介 2. API介绍 2.0 key_t和标识符 2.1  创建system v共享内存 2.2 映射共享内存并使用 2.3 取消共享内存映射 2.4 控制共享内 ...

  8. linux open 头文件_linux下通过共享内存和mmap实现进程间通讯

    前言 最近在学习GNU/Linux内核,看到mmap的时候书上说: mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存.读写大文件.链接动态库文件,还是多进程间共 ...

  9. linux进程间通信:system V 信号量和共享内存实现进程间同步

    关于信号量和共享内存的相关描述已经在前几篇提到过: 信号量:即内核维护的一个正整数,可以使用内核提供的p/v接口进行该正整数的+/-操作,它主要用来表示系统中可用资源的个数,协调各个进程有序访问资源, ...

最新文章

  1. Cannot change version of project facet Dynamic Web Module to 3.0.
  2. 64位Linux下JVM内存调设遇到GC问题的备忘
  3. window 添加环境变量
  4. oracle管理mysql_oracle表管理
  5. mysql某一列之前加一个球_MySQL作业:三色球,概率题,子查询【诗书画唱】
  6. 5G NR SRS (R15)
  7. 西安电子科技大学833真题_【2019更新版】西安电子科技大学计算机软件考研信息汇总...
  8. linux generic什么意思_Linux下ps aux中进程状态为Ss,S+, Rs,Ds是什么意思?
  9. 《转载》python爬虫实践之模拟登录
  10. 脱欧临近引民众忧心食品短缺 英“脱欧生存包”热卖
  11. 高等代数期末考试题库及答案_数学类高等代数期末考试试题A卷(含答案)
  12. PythonNote036---python中字典合并
  13. 笔记本电脑属于下列哪一类型的计算机,除尘清灰成本相差百倍!你的笔记本属于哪一类?...
  14. SketchUp: Modeling Interiors from Photos SketchUp:从照片建模室内设计 Lynda课程中文字幕
  15. 华硕天选2/系列切换应用声音消失问题的解决方法
  16. 愿所有程序都有接口,愿所有接口说明都通俗易懂,更新及时
  17. 怎样修改计算机用户文件名,win10修改用用户文件夹名字怎么操作_win10更改用户文件夹名称方法...
  18. sourcetree提交报错 git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks ······
  19. 怎样将文件后缀名统一重命名并为大写字母
  20. 【控制系统数字仿真与CAD——实验报告】实验四:黄金分割法最优化PI调节器参数(文末附完整代码 + 实验结果)

热门文章

  1. 一个资深系统管理员的O2O实践(三)
  2. Webpack打包构建太慢了?试试几个方法
  3. 【学神】1-16 网络管理相关命令
  4. Mysql整库导出导入
  5. Corn Fields 玉米田
  6. TCP/UDP通信解疑
  7. java-Hyper-V
  8. Java 获得Class的绝对路径方法
  9. GAdminHttpd:图形化的 Apache 打点对象
  10. 配置 IIS 7 显示详细错误信息