栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

进程间通信

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

进程间通信

每个进程间用户空间是独立的,但内核空间是共享的,因此进程间通信要借助内核。

1、管道

管道就是内核里面的一串缓存,管道传输的数据是无格式的字节流且大小受限。不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则。

管道通信方式效率低,不适合进程间频繁交换数据,这是因为一个进程写入数据后,必须等到管道中数据被读取了,命令才可以正常退出。优点是简单。

匿名管道

ps auxf | grep mysql,其中|就是一个管道,将前一个命令的输出作为后一个命令的输入,管道传输数据时单向的。匿名管道的生命周期随进程创建而创建,随进程结束而销毁。

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

在匿名管道的创建背后原理是,系统创建一个匿名管道,并返回两个描述符,一个是管道读取端描述符fd[0],一个是写入端描述符fd[1]。以上两个描述符都存在同一个进程中,如果两个进程想建立通信,就要通过创建子进程,子进程会复制父进程的文件描述符,从而实现通信。

命名管道

也叫FIFO,数据是先进先出的传输方式,通过mkfifo命令创建,mkfifo mypipe。

对于命名管道,他可以在不相关的进程间进行通信,因为命名管道提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,皆可以相互通信。

2、消息队列

消息队列是保存在内核中的消息链表,可以解决管道通信效率低的问题。发送的数据是自定义的消息体,消息队列生命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列一直存在。

缺点:

1、消息队列不适合比较大数据的传输,因为内核中每个消息体有一个最大长度,并且队列也有最大长度限制

2、消息队列通信过程中,存在用户态和内核态之间的数据拷贝开销。

3、共享内存

共享内存可以解决消息队列通信方式用户态和内核态数据拷贝开销。共享内存机制,就是拿出一块虚拟地址空间,映射到相同的物理内存中。这样这个进程写入的东西,另一个进程马上看到,不需要拷贝,大大提高进程间通信速度。

缺点:多个进程同时修改同一共享内存,会带来冲突。

4、信号量

信号量保证共享的资源,在任意时刻只能被一个进程访问。

信号量是一个整型计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。

信号量表示资源的数量,控制信号量有两种原子操作:

  • P操作,用在进入共享资源之前,这个操作会将信号量减一,如果相减后信号量<0,表明当前资源被占用,进程需阻塞等待;如果相减后信号量>=0,表示还有资源可用,进程可以正常执行。
  • V操作,用在离开共享资源之后,这个操作会将信号量加一,相加后信号量<=0,表明当前有阻塞的进程,于是会将该进程唤醒;相加后信号量>0,表明当前没有阻塞的线程。

信号量初始化为1,代表互斥信号量,保证共享数据在任何时刻只能被一个进程访问。

信号量初始化为0,代表同步信号量,保证进程A在进程B之前执行。

5、信号

对于异常情况下的工作模式,需要利用信号的方式通知进程,在Linux操作系统中,提供了几十种信号。信号的来源主要有硬件来源(键盘Ctrl + C)和软件来源(kill命令)。

信号是进程间通信机制中唯一的异步通信机制,一旦有信号产生,进程对信号的处理方式主要有三种:

  • 执行默认操作
  • 捕捉信号,为信号定义一个信号处理函数,信号发生时,执行信号处理函数
  • 忽略信号
6、Socket

要想实现跨网络与不同主机上的进程之间通信,就需要Socket通信。另外socket也可以用于同主机上进程通信。

socket的创建:int socket(int domain, int type, int protocal)

domain用于指定协议族,type用于指定通信特性(如字节流,报文),protocal用于指定通信协议。创建的socket不同,通信方式就不同。

比如:针对TCP协议的socket编程模型

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

这里需要注意的是,服务端调用 accept 时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883290.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号