你知道进程间怎么通信吗?

进程间通信

  • 一、管道
    • 创建管道
    • 父子进程的管道单向通信
    • 父子间的双向通信管道
    • Shell中的管道通信
    • 匿名管道与命名管道
    • 管道特点
  • 二、消息队列
    • 不足
  • 三、共享内存
  • 四、信号量
  • 五、信号
  • 六、Socket
    • 创建Socket的系统调用
    • 通信方式
    • TCP协议通信的Socket编程模型
    • UDP协议通信的Socket编程模型
    • 本地进程间通信的Socket编程模型

进程是相互独立的,他们之间的通信只能通过内核。

一、管道

创建管道

匿名管道的创建,需要通过下这个系统调用:
这里表示创建⼀个匿名管道,并返回了两个描述符,

  • ⼀个是管道的读取端描述符 fd[0]
  • ⼀个是管道的写入端描述符 fd[1] 。

这个匿名管道是特殊的文件,只存在于内存,不存于文件系统中。
其实,所谓的管道,就是内核里面的⼀串缓存。从管道的⼀段写入的数据,实际上是缓存在内核中的,另⼀端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。

父子进程的管道单向通信

使用fork创建子进程,创建的子进程会复制父进程的文件描述符,这样就做到了两个进程各有两个fd[0]fd[1],两个进程就可以通过各自的 fd 写入和读取同⼀个管道文件实现跨进程通信了。

父子间的双向通信管道

如果需要双向通信,则应该创建两个管道。

Shell中的管道通信

在 shell里面执行A | B 命令的时候,A 进程和 B 进程都是 shell 创建出来的子进程,A 和 B 之间不存在父子关系,它俩的父进程都是 shell。

匿名管道与命名管道

  • 匿名管道:通信范围存在父子关系的进程。因为它没有管道文件,只能通过fork复制父进程的fd文件描述符。
  • 命名管道:对于命名管道,它可以在不相关的进程间也能相互通信。因为命令管道,提前创建了⼀个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信。

管道特点

  • 管道传输数据是单向的,如果想相互通信,我们需要创建两个管道。
  • 管道这种通信方式效率低,不适合进程间频繁地交换数据。
  • 简单,同时也我们很容易得知管道⾥的数据已经被另⼀个进程读取了。

二、消息队列

消息队列是保存在内核中的消息链表,在发送数据时,会分成⼀个⼀个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型, 所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。 消息队列⽣命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列会⼀直存在,二而前面提到的匿名管道的生命周期,是随进程的创建而建立,随进程的结束而销毁。消息这种模型,两个进程之间的通信就像平时发邮件⼀样,你来⼀封,我回⼀封,可以频繁沟通了

不足

  • 通信不及时
  • 附件有大小限制

三、共享内存

共享内存的机制,就是拿出⼀块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西, 另外⼀个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。

四、信号量

为了防止进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只 能被⼀个进程访问。正好,信号量就实现了这⼀保护机制。
信号量其实是⼀个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。
信号量表示资源的数量,控制信号量的方式有两种原子操作

  • P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使用,进程可正常继续执行
  • V 操作,这个操作会把信号量加上 1,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程

P 操作是用在进⼊共享资源之前,V 操作是⽤在离开共享资源之后,这两个操作是必须成对出现的。

  • 信号初始化为 1 ,就代表着是互斥信号量,它可以保证共享内存在任何时刻只有⼀个进程在访问,这就很好的保护了共享内存
  • 信号初始化为 0 ,就代表着是同步信号量,它可以保证进程 A 应在进程 B 之前执行

五、信号

上面说的进程通信,是常规模式状态下的工作模式。对于异常情况下的工作模式,就需要用信号的方式来通知进程。
信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)。 信号是进程间通信机制中唯⼀的异步通信机制,因为可以在任何时候发送信号给某⼀进程,⼀旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式

  • 执行默认操作,Linux 对每种信号都规定了默认操作
  • 捕捉信号,我们可以为信号定义⼀个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。
  • 忽略信号,当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP ,它们用于在任何时候中断或结束某⼀进程。

六、Socket

管道、消息队列、共享内存、信号量和信号都是在同⼀台主机上进⾏进程间通信,那要想跨网络与不同主机上的进程之间通信,就需要 Socket 通信了。 Socket 通信不仅可以跨⽹络与不同主机的进程间通信,还可以在同主机上进程间通信。

创建Socket的系统调用

int socket(int domain, int type, int protocal)
三个参数分别代表

  • domain:用来代表指定协议族,比如AF_INET用于IPV4、AF_INET6用于IPV6、AF_LOCAL/AF_UNIX用于本机
  • type:用来指定通信特性,比如SOCK_STREAM表示的是字节流,对于TCP、SOCK_DGRAM 表示的是数据报,对应 UDP、SOCK_RAW 表示的是原始套接字
  • protocal:原本是用来指定通信协议的,但现在基本废弃。因为协议已经通过前面两个参数指定完成,protocol目前⼀般写成 0 即可

通信方式

根据创建 socket 类型的不同,通信的方式也就不同

  • 实现 TCP 字节流通信: socket 类型是AF_INET和SOCK_STREAM
  • 实现 UDP 数据报通信:socket 类型是AF_INET 和 SOCK_DGRAM
  • 实现本地进程间通信: 本地字节流 socket类型是 AF_LOCAL和 SOCK_STREAM,本地数据报 socket 类型是 AF_LOCAL 和SOCK_DGRAM。另外,AF_UNIX 和 AF_LOCAL 是等价的,所以 AF_UNIX 也属于本地 socket

TCP协议通信的Socket编程模型

  • 服务端和客户端初始化 socket ,得到文件描述符
  • 服务端调用bind ,将绑定在 IP 地址和端口
  • 服务端调用listen ,进行监听
  • 服务端调用accept ,等待客户端连接
  • 客户端调用connect ,向服务器端的地址和端⼝发起连接请求
  • 服务端accept返回用于传输的socket的文件描述符
  • 客户端调用write写入数据
  • 服务端调用read 读取数据
  • 客户端断开连接时,会调用close ,那么服务端read读取数据的时候,就会读取到了EOF ,待处理完数据后,服务端调调用 close ,表示连接关闭。

UDP协议通信的Socket编程模型

UDP是没有连接的,所以不需要三次握⼿,也就不需要像 TCP调用listen和connect,但是UDP的交互仍然需要 IP 地址和端口号,因此也需要 bind。对于UDP 来说,不需要维护连接,那么也就没有所谓的发送方和接收方,甚⾄都不存在客户端和服务端的概念,只要有⼀个 socket多台机器就可以任意通信,因此每⼀个UDP 的 socket 都需要 bind。另外,每次通信时,调用sendto和recvfrom,都要传入目标主机的 IP地址和端口。

本地进程间通信的Socket编程模型

本地 socket 被用于在同⼀台主机上进程间通信的场景:

  • 本地socket的编接口和 IPv4 、IPv6 套接字编程接口是⼀致的,可以支持字节流和数据报」两种协议
  • 本地 socket 的实现效率大高于 IPv4 和 IPv6 的字节流、数据报 socket 实现
  • 对于本地字节流 socket,其 socket 类型是 AF_LOCAL 和 SOCK_STREAM。 对于本地数据报 socket,其socket 类型是 AF_LOCAL 和 SOCK_DGRAM。 本地字节流 socket 和 本地数据报 socket 在 bind 的时候,不像 TCP 和 UDP 要绑定 IP 地址和端口,而是绑定⼀个本地文件,这也就是它们之间的最大区别。
(0)

相关推荐

  • 进程间的五种通信方式介绍

    进程间通信又叫IPC (InterProcess Communication)是指在不同进程之间传播或交换信息.IPC的方式通常有管道(包括无名管道和命名管道).消息队列.信号量.共享存储.Socke ...

  • linux各种通讯机制汇总

    eventfd -- 创建一个文件描述符fd,用于支持事件等待通知机制 ,  功能上类似于信号量. 使用场景:当使用pipe仅用于等待/通知功能时,可以使用eventfd替换,代价低,只需要一个文件描 ...

  • 专题:交换机不同vlan间如何通信?两个实例一次了解清楚

    前面我们曾提到关于交换机的4种网络结构方式,你了解几种?,有朋友问到,vlan间需要什么才能通信呢?如何让不同vlan之间通信,我们通常提到了,vlan间通信需要三层交换机,那么不用三层交换机能不能通 ...

  • 通用操作系统的进程间通讯

    前面以Linux为原型,讲述了很多基本的知识.在任务调度的时候,提出了一个概念,就是每个任务在运行时侯,都是占据处理器里面最合理的可占据资源的,并且每个任务运行时候,都是独立的内存分配,独立的处理器数 ...

  • 6种Linux进程间的通信方式 | 《Linux就该这么学》

    进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放.可以认为进程是一个程序的一次执行过程. 进程通信的概念 进程用户空间是 ...

  • 【JAVA并发第三篇】线程间通信

    线程间的通信 JVM在运行时会将自己管理的内存区域,划分为不同的数据区,称为运行时数据区.每个线程都有自己私有的内存空间,如下图示: Java线程按照自己虚拟机栈中的方法代码一步一步的执行下去,在这一 ...

  • RTOS任务间通信和全局变量有什么区别?

    RTOS任务间通信和全局变量有什么区别?

  • Dev Cell:细胞“指尖”变形为细胞外囊泡助力细胞间通信

    来自日本奈良科学技术研究所的研究人员扩大了细胞结构的已知功能范畴,并可能在伤口愈合和癌症治疗中得到应用. 如果你发现只用一根手指就能复原整个机体?这听起来像科幻小说,让人想起1982年的电影<E ...

  • 三种实现VLAN间通信的方式,实现VLAN间通信

    前言: ·传统交换二层组网中,默认所有网络都处于同一个广播域,这带了诸多问题.VLAN(Virtual Local Area Network,虚拟局域网)技术的提出,满足了二层组网隔离广播域需求,使得 ...

  • vue之父子组件间通信实例讲解(props、$ref、$emit)

    组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.那么组件间如何通信,也就成为了vue中重点知识了.这篇文章将会通过props.$ref ...