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大小 文件名
相关推荐
可问 可问春风1 小时前
Linux 找回 Root 密码(多发行版本)
linux·运维·chrome
lllsure2 小时前
【快速入门】MyBatis
java·后端·mybatis
叶雅茗2 小时前
PHP语言的区块链扩展性
开发语言·后端·golang
木子欢儿3 小时前
Debian系统清理垃圾
linux·运维·服务器·debian
谷晓光4 小时前
python中print函数的flush如何使用
linux·服务器·数据库
Hacker_Albert4 小时前
Linux 内核模块签名
linux
Stark、4 小时前
【MySQL】多表查询(笛卡尔积现象,联合查询、内连接、左外连接、右外连接、子查询)-通过练习快速掌握法
数据库·后端·sql·mysql
AdrichPro4 小时前
4、linux c 进程
linux·运维·服务器·c语言
Asthenia04125 小时前
Spring编程式事务全解析:从DataSource到TxManager再到TxTemplate
后端
Moment5 小时前
如果你想找国外远程,首先让我先给你推荐这几个流行的技术栈 🤪🤪🤪
前端·后端·github