Linux进程间通信(1)-管道、内存映射

无名管道

unix最古老的管道:

  • 半双工(只能进行一个方向的读写)
  • 在内存缓存区中(所以不属于文件系统),大小由系统决定,使用ulimit -a查看
  • 数据先入先出且按字节(所以没有格式)传出,读取后就抛弃
  • 只能在具有公共祖先(3代以内)的进程中使用

创建

#include <unistd.h>

int pipe(int filefd[2]);

  • filefd也是用来接受返回的,接受两个文件描述符
  • 创建的管道使用文件描述符进行操作
  • 管道pipefd[0]用于读,pipefdp[1]用于写
  • 失败返回-1

操作

与文件操作一样,都是调用write、read,只是由于只能先进先出,所以不能使用lseek()等函数

读写控制

阻塞只与管道有关,而不是与write和read函数相关,管道的读写都有计数器,close相应管道后就会对应-1

读管道(阻塞):

  • 管道中有数据,read返回实际读取的字节数
  • 无数据
    • 写端计数为0,则直接返回0,且不会修改buffer;
    • 仍然有写端,则阻塞

写管道:

  • 读端为0,进程异常终止
  • 仍有读端
    • 管道已满,write阻塞
    • 管道未满,write将数据写入,并返回实际写入的字节数

读管道(非阻塞)

  • 写端没有关闭,管道没有数据,直接返回-1

  • 设置方法:

    c 复制代码
    int flags = fcntl(fd[0],F_GETFL);
    flag |= O_NONBLOCK;
    fcntl(fd[0],F_SETFL,flags);

有名管道FIFO

  • 就是一个特殊文件,内容放置于内存,程序能及时写入读取
  • 对通信进程不做要求

创建

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *filename, mode_t mode);

  • mode就是设置权限,和chmod一样,如644
  • shell中创建:mkfifo 文件名

操作

  1. 首先打开该管道(文件)获得文件描述符
  2. 后续与文件操作一样,只是不能使用lseek

读写控制

  • 以只读/只写形式打开文件,会阻塞等待另一个进程只写/只读形式打开
  • 和无名管道一致

存储映射(内存映射)

  1. 本质上是将文件指定区域映射到程序的内存中,程序对此部分内存的操作就是对文件的操作,减少系统调用write、read,进而减少了模态切换而造成的开销
  2. 如果两个进程同时对一个文件同块区域进行了存储映射,那这两个进程就实现了通信
  3. 每次都需要一个文件会很麻烦,系统提供了匿名存储映射,不需要提供文件,但是只能用于父子进程,因为此时两者都具有指向该内存空间的指针

创建

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

  • addr 指定内存指针,一般设置NULL让系统自行分配
  • length 设置内存、文件映射区域大小,注意文件分配的内存要>=length
  • prot 设置该区域的访问权限PROT_WRITE|PROT_READ
  • flags 设置该区域数据被修改后程序的行为,MAP_SHARED|MAP_ANONYMOUS
  • fd 文件描述符,匿名映射可以不设置
  • offset 设置文件从哪开始映射到内存中
  • 如果成功则返回指向该区域的内存指针,否则返回MAP_FAILED

操作

  1. 首先打开文件,获得文件描述符(匿名不需要)
  2. 调用
c 复制代码
void  *addr = mmap(NULL,512,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  1. 关闭文件(匿名不需要)
  2. 写存储映射区
  3. 断开存储映射munmap(addr,1024)

补充

  1. 何时写入磁盘?
  • flag为MAP_SHARED,由系统决定何时写回
    • munmap调用
    • 程序退出
    • 系统内存不足
  • 强制写回:
    int msync(void addr[.length], size_t length, int flags); 其中flags为NS_ASYNC
  1. 能否感知文件内容变化
  • flag为MAP_SHARED时,能直接感知到其他进程对文件内容的更新(注意其他进程得写回磁盘);
  1. 写入的是什么?
  • 将映射内存的全部内容直接覆盖原本文件中的指定区域
  1. 如果文件分配的磁盘大小<length会怎么样
  • 出现Bus error (core dumped)
  • 解决方法:创建文件并分配 length 字节的空间
    truncate -s length大小 文件名
相关推荐
对你无可奈何4 分钟前
高可用环境下Nginx服务管理脚本优化实践
linux·运维·nginx
uhakadotcom12 分钟前
MaxCompute Python UDF开发指南:从入门到精通
后端·面试·github
前端snow36 分钟前
爬取数据利用node也行,你知道吗?
前端·javascript·后端
无聊的烤苕皮40 分钟前
RHCE(RHCSA复习:npm、dnf、源码安装实验)
linux·npm·云计算·dnf·rhcsa
xxxx1234451 小时前
Linux驱动开发-①pinctrl 和 gpio 子系统②并发和竞争③内核定时器
linux·驱动开发·单片机
stone08231 小时前
ABAP语言的动态编程(4) - 综合案例:管理费用明细表
linux·运维·服务器
陈随易1 小时前
告别Node.js:2025年,我为何全面拥抱Bun
前端·后端·程序员
uhakadotcom1 小时前
双Token机制:安全与便利的完美结合
后端·面试·github
雷渊1 小时前
java版本管理工具-jenv
后端·架构
厂里英才1 小时前
docker无法正常拉取镜像问题的解决
linux·docker