进程间通信方法(IPC)

进程间通信方法(IPC)

1.概念

  • IPC指的是InterProcess Communication,进程间的通信需要借助操作系统提供的特殊方法,如文件、管道、信号、共享内存、消息队列、套接字、命名管道等等。

  • 进程间通信方式对比:

    • 管道:使用最简单
    • 信号:开销最小
    • 共享映射区:无血缘关系
    • 本地套接字:最稳定

2.管道

  • 管道的特质:

    1. 本质是一个伪文件
    2. 由两个文件描述符引用,一个表示读端,一个表示写端
    3. 规定数据从管道的写端流入,从读端流出
  • 管道的原理:管道实现为内核使用环形队列机制,借助内核缓冲区(4k)实现

  • 管道的局限性:

    1. 数据不能进程自己写,自己读
    2. 管道中的数据不可以反复读取,一旦读走,管道不复存在
    3. 只能在有公共祖先的进程间使用管道
    4. 采用半双工通信方式,数据只能在单方向上流动

3.pipe函数

  • 原型:

    int pipe(int pipefd[2]);
    
  • 作用:创建并打开管道

  • 参数:

    fd[0]:读端

    fd[1]:写端

  • 返回值:

    成功:0

    失败:-1,设置errno

  • 管道的读写行为

    • 读管道

      1. 管道中有数据,read返回实际读到的字节数
      2. 管道中无数据:
        • 管道写端被全部关闭,read返回0(好像读到文件结尾)
        • 管道写端没有全部被关闭,read阻塞等待(不久的将来可能有数据到来,让出CPU)
    • 写管道

      1. 管道读端全部被关闭,进程会异常终止(也可以捕捉SIGPIPE信号,使进程不终止)
      2. 管道读端没有全部关闭:
        • 管道已满,write阻塞(很少见,因为CPU会将缓冲区自动扩容)
        • 管道未满,write将数据写入,并返回实际写入的字数

4.FIFO

  • 功能:创建命名管道,与终端指令mkfifo效果类似

  • 原型:

    int mkfifo(const char* pathname, mode_t mode);
    
  • 参数

    pathname:管道的名称

    mode_t:八进制的权限,比如0664

  • 返回值

    成功:0

    失败:-1,设置errno;

5.存储映射

  • 原理:

    存储映射

  • 相关函数模型:

    void* mmap(void* addr, size_t length, int prot, int flags, int fd, 			   off_t offset);
    
  • 作用:创建共享内存映射

  • 参数:

    add:指定映射区的首地址,通常为NULL,由系统自动分配

    length:共享内存映射区的大小(小于等于文件大小)

    prot:共享内存映射区的读写属性,PROT_READ、PROT_WRITE、PROT_EXEC

    flags:标注共享内存的共享属性,MAP_SHARED、MAP_PRIVATE

    fd:用于创建共享内存映射区的文件描述符

    offset:偏移位置,必须为 4k 的整数倍,默认0表示映射文件全部

  • 返回值:

    成功:映射区的首地址

    失败:MAP_FAILED,设置errno

  • 释放共享内存映射

    int munmap(void* addr, size_t length);
    
  • 参数:

    addr:内存映射的基地址

    length:内存映射的长度

  • 注意事项:

    1. 用于创建映射区的大小为0,实际指定非0大小的映射区,出现”总线错误“

    2. 用于创建映射区的大小为0,实际指定0大小的映射区,出现”参数无效错误“

    3. 用于创建映射区的文件读写属性为只读,映射区为读写,出现”参数无效错误“

    4. 创建映射区,必须要read权限。当访问权限指定为共享MAP_SHARED,mmap的读写权限应该小于等于文件的open权限

    5. 文件描述符,在mmap创建映射区完成即可关闭,后续访问文件用地址访问

    6. offset必须是4096的整数倍

    7. 对申请的内存映射区,不能越界访问

    8. munmap用于释放的地址,必须是mmap申请返回的地址

    9. 映射区访问权限为私有MAP_PRIVATE,对内存所做的所有修改,只在内存有效,不会反应到物理磁盘

    10. 映射区访问权限为私有MAP_PRIVATE,只需要open文件时有读权限,用于创建映射区即可

  • mmap函数的保险调用方式

    • open时设为可读可写
    • mmap设为读写权限,共享模式
    fd = open("文件名", O_RDWR|O_CREAT|O_TRUNC, 0664);
    mmap(NULL, 文件的大小, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    

6.进程间通信

  • 父子进程用mmp进程通信:

    1. 父进程创建映射区。open和mmap函数
    2. 指定MAP_SHARED权限
    3. fork创建子进程
    4. 一个进程读,另外一个进程写
  • 无血缘关系的进程间mmp通信:

    1. 两个进程打开同一个文件,创建映射区
    2. 指定flag为MAP_SHARED
    3. 一个进程写入,另个一进程读出
  • 无血缘关系的进程可以用mmp和fifo进行通信

    • mmp可以反复读取数据
    • fifo只能读取一次数据
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值