进程间通信IPC之--共享内存

时间:2022-04-03 19:29:47

每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲 区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)

如下图所示:
进程间通信IPC之--共享内存
进程间通信共七种方式:
第一类:传统的unix通信机制:

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
 
第二类:System V IPC: 
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
第三类:BSD 套接字:
# 套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
进程间通信IPC之--共享内存
 
本文介绍IPC之共享内存:
共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。进程可以直接读取共享内存,不需要拷贝数据。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
步骤:
共享内存的使用,主要有以下几个API:ftok()、shmget()、shmat()、shmdt()及shmctl()
①创建/打开共享内存
int shmget(key_t key,int size,int shmflag);
例:
key = ftok(".", 'm');
shmid = shmget(key,1024,0666|IPC_CREAT|IPC_EXCL);
参数说明:
key:是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。
产生key的方法:key_t ftok(const char *pathname, int proj_id);
1)pathname一定要在系统中存在并且进程能够访问的
2)proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。如'a',考虑到应用系统可能在不同的主机上应用,可以直接定义一个key,而不用ftok获得:

#define IPCKEY 0x344378

size:申请内存的大小
shmflag:  这块内存的模式(mode)以及权限标识(0666等)。 
 模式可取如下值:        
IPC_CREAT 新建(如果已创建则返回目前共享内存的id)
IPC_EXCL   与IPC_CREAT结合使用,如果已创建则则返回错误 
 其他模式略
申请的内存里面为空,即全为0
②映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
void *shmat( int shmid , char *shmaddr , int shmflag );
例:
void *p;
p=shmat(shmid,NULL,0);
参数说明:
shmid:是那块共享内存的ID。
shmaddr:共享内存映射的起始地址,一般不指定即NULL
shmflag:本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。0是读写模式

返回值: 成功时,这个函数返回共享内存的起始地址。失败时返回-1。

③撤销共享内存映射,删除本进程对这块内存的使用
int shmdt(const void* shmaddr);
例:
shmdt(p);
参数说明:
shmaddr:共享内存的起始地址。
返回值:成功时返回0。失败时返回-1。
④删除共享内存对象
int shmctl( int shmid , int cmd , struct shmid_ds *buf );
例:
shmctl(shmid, IPC_RMID, NULL);(删除共享内存)
参数说明:
shmid:共享内存的ID。
cmd:控制命令,可取值如下:
        IPC_STAT        得到共享内存的状态
        IPC_SET         改变共享内存的状态
        IPC_RMID        删除共享内存
buf:一个结构体指针。用以保存/设置属性。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
返回值:成功时返回0。失败时返回-1。
无代码无真相进程间通信IPC之--共享内存
 
功能说明:两个进程通过共享内存一个写一个读并打印数据
  1. /*name:writer.c
  2. *function:写端进程向共享内存写数据
  3. * */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/ipc.h>
  12. #include <sys/shm.h>
  13. #define N 64
  14. typedef struct
  15. {
  16. pid_t pid;
  17. char buf[N];
  18. } SHM;
  19. void handler(int signo)
  20. {
  21. //printf("get signal\n");
  22. return;
  23. }
  24. int main()
  25. {
  26. key_t key;
  27. int shmid;
  28. SHM *p;
  29. pid_t pid;
  30. if ((key = ftok(".", 'm')) < 0)
  31. {
  32. perror("fail to ftok");
  33. exit(-1);
  34. }
  35. signal(SIGUSR1, handler);//注册一个信号处理函数
  36. if ((shmid = shmget(key, sizeof(SHM), 0666|IPC_CREAT|IPC_EXCL)) < 0)
  37. {
  38. if (EEXIST == errno)//存在则直接打开
  39. {
  40. shmid = shmget(key, sizeof(SHM), 0666);
  41. p = (SHM *)shmat(shmid, NULL, 0);
  42. pid = p->pid;
  43. p->pid = getpid();
  44. kill(pid, SIGUSR1);
  45. }
  46. else//出错
  47. {
  48. perror("fail to shmget");
  49. exit(-1);
  50. }
  51. }
  52. else//成功
  53. {
  54. p = (SHM *)shmat(shmid, NULL, 0);
  55. p->pid = getpid();//把自己的pid写到共享内存
  56. pause();
  57. pid = p->pid;//得到读端进程的pid
  58. }
  59. while ( 1 )
  60. {
  61. printf("write to shm : ");
  62. fgets(p->buf, N, stdin);//接收输入
  63. kill(pid, SIGUSR1);//向读进程发SIGUSR1信号
  64. if (strcmp(p->buf, "quit\n") == 0) break;
  65. pause();//阻塞,等待信号
  66. }
  67. shmdt(p);
  68. shmctl(shmid, IPC_RMID, NULL);//删除共享内存
  69. return 0;
  70. }
  1. /*name:reader.c
  2. *function:读端进程从共享内存中读数据
  3. * */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/ipc.h>
  12. #include <sys/shm.h>
  13. #define N 64
  14. typedef struct
  15. {
  16. pid_t pid;
  17. char buf[N];
  18. } SHM;
  19. void handler(int signo)
  20. {
  21. //printf("get signal\n");
  22. return;
  23. }
  24. int main()
  25. {
  26. key_t key;
  27. int shmid;
  28. SHM *p;
  29. pid_t pid;
  30. if ((key = ftok(".", 'm')) < 0)
  31. {
  32. perror("fail to ftok");
  33. exit(-1);
  34. }
  35. signal(SIGUSR1, handler);//注册一个信号处理函数
  36. if ((shmid = shmget(key, sizeof(SHM), 0666|IPC_CREAT|IPC_EXCL)) < 0)
  37. {
  38. if (EEXIST == errno)//存在则直接打开
  39. {
  40. shmid = shmget(key, sizeof(SHM), 0666);
  41. p = (SHM *)shmat(shmid, NULL, 0);
  42. pid = p->pid;
  43. p->pid = getpid();//把自己的pid写到共享内存
  44. kill(pid, SIGUSR1);
  45. }
  46. else//出错
  47. {
  48. perror("fail to shmget");
  49. exit(-1);
  50. }
  51. }
  52. else//成功
  53. {
  54. p = (SHM *)shmat(shmid, NULL, 0);
  55. p->pid = getpid();
  56. pause();
  57. pid = p->pid;//得到写端进程的pid
  58. }
  59. while ( 1 )
  60. {
  61. pause();//阻塞,等待信号
  62. if (strcmp(p->buf, "quit\n") == 0) exit(0);//输入"quit结束"
  63. printf("read from shm : %s", p->buf);
  64. kill(pid, SIGUSR1);//向写进程发SIGUSR1信号
  65. }
  66. return 0;
  67. }
进程间通信IPC之--共享内存
 

进程间通信IPC之--共享内存的更多相关文章

  1. 进程间通信——IPC之共享内存

        共享内存是三个IPC机制中的一个.它允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在进行的进程之间传递数据的一种非常有效的方式.   大多数的共享内存的实现,都把由不同进程之间共享 ...

  2. 【Linux 应用编程】进程管理 - 进程间通信IPC之共享内存 mmap

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

  3. Linux进程间通信&lpar;System V&rpar; --- 共享内存

    共享内存 IPC 原理 共享内存进程间通信机制主要用于实现进程间大量的数据传输,下图所示为进程间使用共享内存实现大量数据传输的示意图: 共享内存是在内存中单独开辟的一段内存空间,这段内存空间有自己特有 ...

  4. System IPC 与Posix IPC(共享内存)

    系统v(共享内存) 1.对于系统V共享内存,主要有以下几个API:shmget().shmat().shmdt()及shmctl(). 2.shmget()用来获得共享内存区域的ID,如果不存在指定的 ...

  5. Linux IPC之共享内存C 事例

    Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报  分类: Linux(3)  读书札记(3)  版权 ...

  6. 五十、进程间通信——System V IPC 之共享内存

    50.1 共享内存 50.1.1 共享内存的概念 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间.所有用户空间的进程若要操作共享内存,都要将其映射到自己 ...

  7. System V IPC 之共享内存

    IPC 是进程间通信(Interprocess Communication)的缩写,通常指允许用户态进程执行系列操作的一组机制: 通过信号量与其他进程进行同步 向其他进程发送消息或者从其他进程接收消息 ...

  8. Linux 进程间通信&lpar;管道、共享内存、消息队列、信号量&rpar;

           进程通信 : 不同进程之间传播或交换信息    为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...

  9. Linux进程间通信之《共享内存》入门

    目录 简述 代码 写端代码 读取端代码 编译 运行 简述 共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket.之 ...

随机推荐

  1. mybits批量插入

    <!--批量插入--> <insert id="batchSave" parameterType="java.util.List"> i ...

  2. Python基础中所出现的异常报错总结

    今天我们来探索python中大部分的异常报错 首先异常是什么,异常白话解释就是不正常,程序里面一般是指程序员输入的格式不规范,或者需求的参数类型不对应,不全等等. 打个比方很多公司年终送苹果笔记本,你 ...

  3. Web-Nginx配置

    #运行用户 user nobody; #启动进程,通常设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 #error_log logs/error.log; ...

  4. 解决This function or variable may be unsafe

    工程名字右键属性-->C/C++-->预处理器-->预处理器定义-->加入:_CRT_SECURE_NO_WARNINGS

  5. Django中的Ajax

    Ajax 很多时候,我们在网页上请求操作时,不需要刷新页面.实现这种功能的技术就要Ajax!(本人定义,不可迷信) jQuery中的ajax就可以实现不刷新页面就能向后台请求或提交数据的功能,我们仍然 ...

  6. mysql xtrabackup增量备份

    mysql 增量备份策略 周一全备,其他增量备份,根据业务需要,设定保留日期,如保留一月. 增量备份步骤; 1 创建全备 2 根据全备目录,创建增量备份 3 第二次增量备份根据第一次增量备份目录,依次 ...

  7. MVC-HtmlHelper简单总结

    Asp.Net MVC - Htmlhelper 总结 HtmlHelper是一个返回Html字符串的方法.返回的字符串可以是任意类型.例如你可以使用HtmlHelper方法返回一个标准的html标签 ...

  8. 英语口语练习系列-C38-颜色-谈论日常活动

    词汇颜色 color red passion green peace energy blue calm purple mystery yellow royal 询问日常生活 When do you g ...

  9. coredump文件抓取设置

    ulimit -c unlimitedecho 1 > /proc/sys/kernel/core_uses_pidecho "/tmp/core-%e-%s-%u-%g-%p-%t& ...

  10. Bmob后端云使用步骤

    1.登录创建应用后得到id 2.在清单文件中添加权限 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion ...