后台开发:进程间通信

简介

       最简单的进程间通信可以通过文件共享来实现,在同一台机器上,一般的方式有:管道,消息队列,共享内存,信号量,在不同的机器上一般用套接字。

管道

在这里插入图片描述

       父子进程之间不共享数据段和堆栈段,有血缘关系的进程之间用无名管道就可以通信,一般进程之间使用有名管道进行通信。管道是一种单向传输机制,
在这里插入图片描述
       管道所传输的是无格式的字节流,且缓冲区大小有限制。
在这里插入图片描述
在这里插入图片描述
       调用pipe(int fd[2])函数创建一个管道文件,这个王稳健存在于创建他的进程中,因此由这个进程再创建一个子进程与之通信。管道的数据只能从fd[1]写到fd[0]。
       但是,linux进城创建是调用fork函数的,子进程与父进程共享代码段,但有独立的数据段和堆栈,子进程只执行fork之后的代码。对于有些情况,在fork之前的print会被打印两次,并不是代码执行了两次,而是print没有遇到\n,所以数据存在了缓冲区,fork的时候子进程复制了父进程的缓冲区数据段,最终打印的时候也会打出来一个。

过程

创建管道

在这里插入图片描述

子进程执行写操作

在这里插入图片描述

父进程执行读操作

在这里插入图片描述

解释

       无名管道只是单向传递,无论是上述子写给父,还是父写给子,都必须关闭另一个方向的管道文件描述符。
       这又是fork的一个点。还记得在守护进程中的有一步是关闭所有文件描述符,否则可能导致文件系统无法正常关闭。fork在调用pipe函数之后,父子进程拥有相同的文件描述符。就好像每一个文件描述符都执行了dup函数。父子进程的每个打开的文件描述符指向相同的文件表中的一项。
       所以,如果父子进程在通信时不关闭多余的文件描述符,pipe【0】和pipe【1】的引用计数都是2。这里假设父进程读、子进程写,那么父进程就会后于子进程退出(合理的顺序)。子进程退出后,pipe【1】的引用计数仍为1(父进程自己的引用)。此时,父进程去读,pipe【1】文件描述符打开,但是没有进程会向pipe【1】中写入数据,父进程就会阻塞。如果pipe【1】文件描述符关闭,再次read就会返回0,而不是阻塞,就好比读到了文件的末尾。因此,需要关闭另一个方向的管道文件描述符,否则就会导致父进程死锁。
在这里插入图片描述
在这里插入图片描述
管道需要考虑同步问题,多个子进程连接同一个父进程。
在这里插入图片描述

有名管道

区别

在这里插入图片描述

介绍

有名管道提供一个文件路径,本身其实是一个FIFO文件,而不像无名管道是两个文件。

特点

1.用于不相关的进程之间通信。
2.对于文件系统来说是可见的。
3.严格的先入先出规则,从开始处读取数据,写入到管道文件的尾部。

函数原型

原型

过程

在这里插入图片描述
指明FIFO文件位置

在读端创建新的FIFO文件

在这里插入图片描述

在这里插入图片描述
实现读写程序的异步,而非线性。
在这里插入图片描述
可以通过死循环,读返回0说明空,读到说明有。可以用select的思想,只有read返回>0的数,才响应这个读短的请求。

在这里插入图片描述

总结

在这里插入图片描述
阻塞可能是被其他读阻塞,也可能是被写阻塞。
在这里插入图片描述
在这里插入图片描述

消息队列

介绍

类似于无名管道,是一个内核中的队列,以消息链表的方式存储。
在这里插入图片描述
在这里插入图片描述

函数原型

在这里插入图片描述
双方可以共用一个已经存在的队列或者一个创建一个引用。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

过程分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对比

在这里插入图片描述

优点

1.消息队列可以独立于发送和接受进程存在,避免了同步命名管道打开关闭的困难。
2.多个客户端可以同时发消息,不需要线程本身实现同步。因为消息msg_st的msgtype可以制定不同的客户端。
3.接收端也可以选择性的接受。

缺点:快被淘汰了

共享内存

在这里插入图片描述

概念

两个进程访问俄一个逻辑内存,共享内存一般在同一个物理段中。进程可以吧共享内存连接到进程的地址空间即可。

需要其他的同步机制

函数原型

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码详解

整体思路

在这里插入图片描述
读端创建共享内存,然后把这段内存的地址链接到自己的进程地址空间。
写端取得共享内存地址,把他链接到自己的进程地址空间。
共享内存通过一个标志位实现同步,类似于但生产者–消费者模型。

读端:consumer

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写端:producer

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

优点和缺点

在这里插入图片描述
这个程序只实现了读—写同步,没有实现读—读同步,需要设置wirtten标志位的值为写入的生产者进程数量。
而且对共享内存这个标志位的操作不是原子操作,无法保证有效读取。
这就引出了下一种方式:信号量。

信号量

在这里插入图片描述

简介

多线程信号量是POSIX信号量,多进程是SYSTEM V信号量。二者本质上都是用户态下进程可使用的信号量。

函数原型

semget

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

semop

在这里插入图片描述
在这里插入图片描述

semctl

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

应用

结合共享内存,解决不同步的内存读写问题。

代码详解

共享内存的部分省略

reader

在这里插入图片描述
在这里插入图片描述

writer

在这里插入图片描述
在这里插入图片描述

ipcs命令

用于查看系统的管道,消息队列,共享内存,信号量等状态。
-a:所有
-q:消息队列
-s:信号量
-m:共享内存
-u:当前使用状况
-l:系统限额

总结

这些都是长连接的例子,后面会介绍HTTP短连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星辰的野望

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

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

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

打赏作者

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

抵扣说明:

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

余额充值