进程间的通信方式

一 进程通信概念

进程间为什么需要通信?计算机给进程在内存中分配的位置是不一样的,正是因为这种隔离,不像线程那样共享资源,因此需要通信。但是进程之间互相并不知道其他进程的位置,所以进程之间交换数据必须通过内核,在内核中开辟一块缓冲区,进程一把数据从用户空间拷贝到缓冲区,进程二从缓冲区把数据读走,内核提供的这种机制称为进程间通信。
举个例子:上古时期有一个村落,地广人稀,每一户人家间隔都很远,互相不知道住在哪(进程之间不知道位置)。但是村子有村长管理,村长住的地方是村子的集会中心(内核),村长知道所有人的地址,因此不同家庭之间想要交流就需要先告诉村长,由村长把他们要讲的消息存起来(缓存区),让另一户人家来读。

二 进程间通信方式

2.1 管道/匿名管道

  • 是一种半双功的通信方式,只能单向传输数据,如果双方需要通信,那么需要开两个管道
  • 对于管道两边的进程来说,就是一种文件,是一种独立的文件系统,不属于任何文件系统,自成一脉并且只存在于内存中
  • 由于没有名字,所以只能在具有亲缘关系的进程间通信
  • 读写时,进程A将数据写入管道尾,进程B将数据从管道头读出

管道的实质

  • 说白了,管道还是一种内核缓存区
  • 可以将管道看成一个循环队列,首尾都是自动增加的,不可以随意修改,读空之后管道的数据就不存在了
  • 如果将管道读空或者写满,读进程或者写进程就会进入等待队列,当管道中新数据写入或者有空余位置时,就唤醒读进程或者写进程

局限

  • 半双工,只支持单向数据流
  • 只能用于亲缘进程间
  • 没有名字
  • 大小有限
  • 管道传送的是无格式字节流,要求进程双方传输前就约定好数据格式

2.2 有名管道(FIFO)

  • 为客服无名管道的缺点而提出的有名管道
  • 提供了一个路径名与之关联,以有名管道的文件形式存在内存中,通信双方只要知道该路径名便可通过路径名访问该管道实现通信
  • 有名管道的名字存在文件系统中,内容存在内存中,严格遵循FIFO
  • 一个进程以读方式打开管道时,另一个进程必须以写方式打开此管道,反之亦然,否则进程会阻塞

2.3 信号

  • 是linux系统中进程间用于通信的一种常见方式,可以在任意时刻由一个进程发送给任意一个进程,不用管该进程是否在运行
  • 如果目标进程不在执行状态,则内核会先保存信号,等该进程执行并通知内核后内核才会将信号发给该进程
  • 同时目标进程还可以设置是否阻塞信号,如果阻塞,那么该信号的传递被延迟,直到阻塞取消该信号才会被发送

来源

信号主要有来源:

  • 硬件层面:ctrl+c退出和硬件异常
  • 软件层面:终止进程,其他进程调用kill函数,软件异常产生

2.4 消息队列

  • 与管道不同,只存在于内核中,由链表组成
  • 只有在内核重启或者显示删除队列时才会真正消失
  • 在写入时不需要有一个进程开启同步地读出

特点

  • 是消息的链表,存在于内存中并由消息队列标识符标记,有自己的格式
  • 和管道一样遵循先进先出策略
  • 允许多个进程同时读写消息
  • 不一定要按照先进先出读取,也可以按照消息类型读取,更加灵活
  • 缓存大小不受限,并且写入的消息可以带类型,因此承载更多的信息
  • 目前主要有两种消息队列,一种是POSIX消息队列,一种是System V消息队列。目前System V消息队列被广泛使用。存在于系统内核,只有内核重启或者人工删除时才会队列才会被删除

2.5 共享内存

  • 为了解决各种通信方式效率不高的问题,提出来一种共享内存方式,多个进程可以共享一块内存,是目前效率最高的通信方式
  • 在内核中开辟一块内存,需要访问的进程可以将其映射为自己的私有地址。进程就可以直接读写这块空间,不需要拷贝数据,效率大大提高
  • 多进程共享内存后,就容易出现互相干扰的问题,就和多线程共享进程内存是一个道理,因此常需要信号量来进行进程的同步和互斥

2.6 信号量

互斥

是指某资源同时只允许一个访问者进行访问,具有唯一性和排他性。但是互斥无法限制访问者对资源的访问顺序。

同步

在互斥的基础上(大部分情况下),实现访问者对资源的有序访问

信号量的实现

  • 信号量的目的就是为了实现同步
  • 实现方式是计数器,通过计数来保证多访问的有序性

2.7 Socket套接字

  • 用于不在一台计算机,但可以通过网络连接的两台计算机上的进程实现通信
  • 是tcp/ip协议中实现网络进程通信的基本单元,可以看做不同主机进程间进行通信的端点

套接字三个参数

  • 本机ip地址和目标ip地址
  • 使用的传输层协议(tcp/udp)
  • 端口号

连接过程(类比于tcp三次握手)

  • 服务器监听:服务器端并不会定位客户端套接字,而是监听自己的套接字
  • 客户端请求:客户端要定义好想要通信的服务端套接字,包括ip和端口号,然后提出连接请求
  • 连接确认:服务器端监听到了来自客户端的请求后,开一个新的线程把服务器端套接字描述发送给客户端,客户端确认此描述后就连接好了。然后服务器端重新进入监听状态,监听来自其他客户端套接字的请求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

油光发亮的小猛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值