学习

(1)进程间几种通信方式

2020-12-07  本文已影响0人  hedgehog1112

管道、消息队列、共享内存、信号量、信号、socket

要知道管道、消息队列、共享内存的本质:内存本质、效率以及传输数据要求,各种使用方式

一、管道

管道通信效率低,不适合进程间频繁地交换数据。好处,简单,很容易得知已被另一进程

    匿名管道,通信范围存在父子关系进程。没有管道文件,只能 fork 复制父进程 fd 文件描述符来通信

    命名管道,不相关进程间也能相互通信。因为命令管道,提前创建管道类型设备文件,只要用这个文件,就可通信

相同:都在缓存内核读写先进先出,不支持 lseek 之类文件定位操作

1、匿名管道

$ ps auxf | grep mysql       用完就销毁         

 | 就是一个管道,将前一个命令(ps auxf)输出,作为后一命令(grep mysql)输入,管道传数据是单向,如相互通信,要两个

2、命名管道FIFO   

  $ mkfifo myPipe(名)       用前要mkfifo 命令创建,指定管道名,数据先进先出

1)基于“Linux一切皆文件”,管道也文件,ls 看,文件类型是 p,就是 pipe(管道) 意思

2)往 myPipe 写入数据:因为内容没被读,只有读后,命令才正常退出

3)读出了,echo 命令正常退出

3、创建原理

1)匿名管道创建, 通过  int  pipe(intfd[2]) 系统调用:

两个描述符:管道读取端 fd[0]写入端 fd[1]。ps:匿名管道是特殊文件,只在内存不存文件系统

2)管道,就是内核里一串缓存。读写都在缓存内核中,传数据无格式的流大小受限

3)跨进程通信实现:fork 创建子进程,复制父进程文件描述符,两个进程各有两个「 fd[0] 与 fd[1]」,通过各自fd 读写同一管道文件

4)避免混乱:父进程:关读 fd[0],保留写fd[1]        子进程:关写 d[1],保留读fd[0]

所以,双向通信,应两个管道

5)到这里,仅解析父子进程通信,但shell 里面并不是这样

shell 里:执行 A | B命令时,都是 shell 创建的子进程,不存父子关系,父进程都是 shell

ps:shell 里能使用一个管道搞定的事情,就不要多用一个管道,减少创建子进程开销

二、消息队列

解决频繁地交换数据问题,内核中的消息链表

1、发时,分成一个个消息体(数据块),用户自定义数据类型,固定大小,不像管道无格式字节流数据读后,内核删除消息体

2、生命周期:随内核,没有释放消息队列或没关闭操作系统管道随进程结束销毁

3、不足:通信不及时,大小限制

        用户态内核态数据拷贝开销:写数据内核队列时,从用户态拷到内核态过程,读同理,从内核到用户

        不适合大数据传输,消息体、队列总长都有限制。Linux 内核中有MSGMAX 和 MSGMNB  消息和队列最大长,字节为单位

三、共享内存

解决  用户态与内核间的消息拷贝

1、内存管理:进程有自己独立的虚拟内存空间不同进程虚拟内存映射到不同物理内存中。即使进程 A  B 虚拟地址一样,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。

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

四、信号量

共享内存问题,同时修改同一共享内存,冲突。信号量解决

信号量:整型计数器,表示资源的数量,实现进程间互斥与同步,而不是用于缓存进程间通信数据

1、控制信号量两种原子操作:

    1)P 操作,减 -1,减后:< 0被占用,进程阻塞等待;  >= 0可用,继续执行

    2)V 操作,加 1, <= 0,有阻塞唤醒运行; > 0,没有阻塞

P 在进入共享资源之V 离开成对出现

2、例:两进程互斥访问共享内存,初始化信号量1

先P 操作,信号量变 0,可用,访问共享内存

此时B 也访问, P 操作, -1被阻塞。

A 完V 操作,恢复为 0,唤醒阻塞中B,B 完成执行 V,恢复1

例2,A 负责生产数据,B 是负责读,有顺序。初始化信号量可为 0

五、信号

上面都是常规工作模式。异常用「信号」通知进程,唯一异步通信机制。ps:跟信号量虽然名字相似,用途完全不一样

1、Linux 操作系统, 为响应各种各样事件,提供几十种信号, kill -l 命令,查看所有

2、给进程发送信号

终端输入组合键: Ctrl+C 产生 SIGINT 信号,终止进程;

                              Ctrl+Z 产生 SIGTSTP 信号,停止进程,未结束

                              如果进程在后台运行,用kill+PID 号    kill -9 1050 ,立即结束

3、进程对信号处理方式

    1)执行默认操作:Linux 对每种信号规定默认操作,SIGTERM 信号,终止。Core Dump,终止进程后,通过Core Dump 将当前进程的运行状态保存在文件里,方便事后分析

    2.捕捉信号:定义信号处理函数。信号发生,执行相应函数

    3.忽略信号。不做任何处理。SIGKILL 和 SEGSTOP无法捕捉和忽略,用于任何时候中断或结束某一进程。

六、Socket

跨网络不同主机上进程间通信(也可同主机),要 Socket

1、创建 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 (基本废弃):写成 0 即可,原本是用来指定通信协议的,通过前两个完成

2、不同socket 类型,通信方式不同

    实现 TCP 字节流通信:socket 是 AF_INET 和 SOCK_STREAM;

    实现 UDP 数据报通信:socket 是 AF_INET 和 SOCK_DGRAM;

    实现本地进程间通信:「本地字节流 socket 」类型是 AF_LOCAL 和 SOCK_STREAM,「本地数据报 socket 」类型是 AF_LOCAL 和 SOCK_DGRAM。ps:AF_UNIX 和 AF_LOCAL 是等价的,所以 AF_UNIX 也属于本地 socket;

3、三种通信编程模式

(1)TCP 协议通信socket 编程模型

    1)服务端和客户端初始化 socket,得到文件描述符;

    2)服务端调bind,绑定IP 地址和端口;    调listen监听;调accept,等待客户端连接;

    3)客户端调connect,向服务器端的地址和端口发起连接请求;

    4)服务端 accept 返回用于传输的 socket 文件描述符;ps:连接成功返回已完成连接socket,通过read 和 write 读写,像往文件流里面写东西一样

    5)客户端调 write 写入数据;服务端调用 read 读取数据;

    6)客户端断开连接时调用 close,那么服务端 read 读取数据时,读到EOF,处理完close

监听socket  和 真正传数据socket(已完成连接 socket),是「两个」 socket

(2)针对 UDP 协议通信的 socket 编程模型

    1)只要 IP 地址端口号、bind,UDP没连接,不需要三次握手,不需像 TCP 调listen 和 connect,。

    2)每次通信,调sendto 和 recvfrom,传入目标主机的 IP 地址端口

(3)本地进程间通信socket 编程模型

    用于同一主机通信的,

    1)接口和 IPv4 、IPv6 套接字编程一致,支持「字节流」和「数据报」两种协议;效率大大高于 IPv4 和 IPv6 字节流、数据报 socket 实现;

        本地字节流 socket,socket 类型AF_LOCAL 和 SOCK_STREAM。

        本地数据报 socket,AF_LOCAL 和 SOCK_DGRAM。

    2)两个bind 时绑定一个本地文件,不像 TCP 和 UDP 要绑定 IP 地址和端口,最大区别

总结

每个进程都共享一个内核空间,来通信

1、Linux 内核提供「匿名管道」和「命名管道」:都写入缓存在内核中,另一个进程也从内核读,先进先出,不支持 lseek 文件定位

    匿名:「|」竖线就是匿名管道,通信数据无格式的流并且大小受限单向,双向要建两个管道,只能用于父子关系通信,随着进程创建而建,终止而消失

    命名管道:突破父子限制,使用前提,要文件系统创建类型 p 的设备文件。

2、消息队列:解决管道无格式的字节流的问题,实际是保存在内核「消息链表」,用户可自定义消息体,发时被分成,一个个独立消息体,接时保持一致,不是最及时的,读写要经过用户态与内核态之间的拷贝过程。

3、共享内存:解决拷贝开销,直接分配共享空间,进程可直接访问,提高速度,缺点:多进程竞争同个共享资源错乱

4、信号量:实现互斥访问。实际是计数器(资源个数),P 和 V 操作控制

5、信号唯一异步通信机制,在应用进程和内核直接交互,内核用信号来通知用户,进程发生了哪些系统事件,三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。ps:SIGKILL 和 SEGSTOP无法捕捉和忽略,方便任何时候结束进程

6、Socket:与不同主机的进程间通信,那么就需要 通信了。根据Socket不同类型,分为三种通信方式, TCP、UDP、本地进程间

https://mp.weixin.qq.com/s/MnIcTR0KKpgnSoA3xaPUSA

上一篇下一篇

猜你喜欢

热点阅读