进程间通信

全文目录

  • 相关概念
  • 管道
    • 实现方法
    • 匿名管道
    • **总结**
    • 命名管道
      • **命名管道打开规则:**
    • 命名管道和匿名管道的区别:
  • system v 共享内存
    • 创建共享内存
    • 挂接和脱离共享内存
    • 控制共享内存
    • 总结
  • 临界资源

相关概念

本质:

因为进程具有独立性,所以进程通信的本质就是让不同进程看到同一块资源。这块资源不属于任何一个进程。

必要性:

为了实现传输数据,同步执行流等多进程协同功能

管道

把从一个进程连接到另一个进程的一个数据流称为一个“管道”

进程间通信_第1张图片

实现方法

当fork创建子进程时,进程相关的文件描述符会被拷贝一份,但是文件不会被拷贝一份,也就是说父子进程的同一个文件描述符会指向同一个文件。

进程间通信_第2张图片

在内核角度,管道本质与文件一样:

进程间通信_第3张图片

匿名管道

pipe函数:

进程间通信_第4张图片
进程间通信_第5张图片

总结

  • 只能用于具有血缘关系的进程之间进行通信
  • 管道是单向通信的,就是半双工的一种特殊情况
  • 管道提供的是面向流式的通信服务 —— 面向字节流 —— 协议
  • 管道是基于文件的,文件的生命周期随进程 —— 管道的生命周期随进程
  • 管道提供了访问控制
    • 写快,读慢,写满就不能写了

    • 写慢,读快,管道没有数据的时候,读必须等待

    • 写关,读只能读到0,表示读到了文件结尾

    • 读关,写继续写,OS终止写进程

命名管道

在不想关进程之间通信时,可以使用FIFO文件来实现,也被叫做命名管道:存在于磁盘上,在系统中有唯一的路径,并且不会将数据从内存刷新到磁盘的文件

进程间通信_第6张图片

在文件中删除管道:

int unlink(const char *pathname);

命名管道打开规则:

进程间通信_第7张图片

命名管道和匿名管道的区别:

在这里插入图片描述

system v 共享内存

与动态库的原理一致,一块内存映射在不同进程的堆栈之间。

进程间通信_第8张图片

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据,而是直接进行内存级的读和写。

共享内存需要被OS管理,所以共享内存 = 共享内存块 + 对应的共享内存的内核数据结构!

进程间通信_第9张图片

创建共享内存

进程间通信_第10张图片

挂接和脱离共享内存

进程间通信_第11张图片

控制共享内存

进程间通信_第12张图片

删除共享内存:

ipcrm -m shmid 	# 删除指定共享内存
shmctl(shmid, IPC_RMID, nullptr);

总结

  • 共享内存在进程间通信(IPC)中速度最快是因为减少了拷贝次数

普通管道文件(四次拷贝):
外设 ——> 用户级缓冲区 ——> 管道文件 ——> 用户级缓冲区 ——> 外设
共享内存(两次拷贝):
外设 ——> 共享内存 ——> 外设

  • 共享内存缺乏访问控制(可以通过管道进行访问控制)

临界资源

进程间通信本质就是让不同的进程看到同一块资源,这也会带来一些时序性问题,造成数据不一致问题。

  1. 多个进程(执行流)看到的公共的资源 —— 临界资源
  2. 访问临界资源的代码 —— 临界区

多个执行流,运行时互相干扰,主要是因为不加保护的访问了同样的资源(临界资源),在非临界区多个执行流互相是不影响的。

  1. 为了保护临界区,可以让多执行流在任何时刻都只能有一个进程进入临界区 —— 互斥

信号量就是为了保护临界资源而来的,本质是一个计数器的(与信号是两个概念)。保证只有一个进程能够访问临界资源,访问临界资源信号量–,访问结束信号量++。信号量的操作是原子性的。

  1. 原子性:不可再被分割,没有中间状态·。

你可能感兴趣的:(Linux,网络,服务器,Linux)