首页 > 系统相关 >进程间通信

进程间通信

时间:2023-02-15 13:22:27浏览次数:47  
标签:信号量 Socket 间通信 管道 进程 共享内存 服务端

6种方式:管道、消息队列、共享内存、信号量、信号、socket

前提知识:每个进程都有自己的用户空间,而内核空间是每个进程共享的。因此进程之间想要进行通信,就需要通过内核来实现。

管道

管道是最简单,效率最差的一种通信方式。

管道本质上就是内核中的一个缓存,当进程创建一个管道后,Linux会返回两个文件描述符,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道写入或者读取数据。

如果想要实现两个进程通过管道来通信,则需要让创建管道的进程fork子进程,这样子进程们就拥有了父进程的文件描述符,这样子进程之间也就有了对同一管道的操作。

缺点:

半双工通信,一条管道只能一个进程写,一个进程读。
一个进程写完后,另一个进程才能读,反之同理。
消息队列:

管道的通信方式效率是低下的,不适合进程间频繁的交换数据。这个问题,消息队列的通信方式就可以解决。A进程往消息队列写入数据后就可以正常返回,B进程需要时再去读取就可以了,效率比较高。

而且,数据会被分为一个一个的数据单元,称为消息体,消息发送方和接收方约定好消息体的数据类型,不像管道是无格式的字节流类型,这样的好处是可以边发送边接收,而不需要等待完整的数据。

但是也有缺点,每个消息体有一个最大长度的限制,并且队列所包含消息体的总长度也是有上限的,这是其中一个不足之处。

另一个缺点是消息队列通信过程中存在用户态和内核态之间的数据拷贝问题。进程往消息队列写入数据时,会发送用户态拷贝数据到内核态的过程,同理读取数据时会发生从内核态到用户态拷贝数据的过程。

共享内存

共享内存解决了消息队列存在的内核态和用户态之间数据拷贝的问题。

现代操作系统对于内存管理采用的是虚拟内存技术,也就是说每个进程都有自己的虚拟内存空间,虚拟内存映射到真实的物理内存。共享内存的机制就是,不同的进程拿出一块虚拟内存空间,映射到相同的物理内存空间。这样一个进程写入的东西,另一个进程马上就能够看到,不需要进行拷贝。

(这里的物理内存貌似不是内核空间的内存?)

信号量

当使用共享内存的通信方式,如果有多个进程同时往共享内存写入数据,有可能先写的进程的内容被其他进程覆盖了。

因此需要一种保护机制,信号量本质上是一个整型的计数器,用于实现进程间的互斥和同步。

信号量代表着资源的数量,操作信号量的方式有两种:

P操作:这个操作会将信号量减一,相减后信号量如果小于0,则表示资源已经被占用了,进程需要阻塞等待;如果大于等于0,则说明还有资源可用,进程可以正常执行。
V操作:这个操作会将信号量加一,相加后信号量如果小于等于0,则表明当前有进程阻塞,于是会将该进程唤醒;如果大于0,则表示当前没有阻塞的进程。
(1)信号量实现互斥:

信号量初始化为1

进程 A 在访问共享内存前,先执行了 P 操作,由于信号量的初始值为 1,故在进程 A 执行 P 操作后信号量变为 0,表示共享资源可用,于是进程 A 就可以访问共享内存。
若此时,进程 B 也想访问共享内存,执行了 P 操作,结果信号量变为了 -1,这就意味着临界资源已被占用,因此进程 B 被阻塞。
直到进程 A 访问完共享内存,才会执行 V 操作,使得信号量恢复为 0,接着就会唤醒阻塞中的线程 B,使得进程 B 可以访问共享内存,最后完成共享内存的访问后,执行 V 操作,使信号量恢复到初始值 1。
(2)信号量实现同步:

由于多线程下各线程的执行顺序是无法预料的,有些时候我们希望多个线程之间能够密切合作,这时候就需要考虑线程的同步问题。

信号量初始化为0

如果进程 B 比进程 A 先执行了,那么执行到 P 操作时,由于信号量初始值为 0,故信号量会变为 -1,表示进程 A 还没生产数据,于是进程 B 就阻塞等待;
接着,当进程 A 生产完数据后,执行了 V 操作,就会使得信号量变为 0,于是就会唤醒阻塞在 P 操作的进程 B;
最后,进程 B 被唤醒后,意味着进程 A 已经生产了数据,于是进程 B 就可以正常读取数据了。
信号

在Linux中,为了响应各种事件,提供了几十种信号,可以通过kill -l命令查看。

如果是运行在shell终端的进程,可以通过键盘组合键来给进程发送信号,例如使用Ctrl+C产生SIGINT信号,表示终止进程。

如果是运行在后台的进程,可以通过命令来给进程发送信号,例如使用kill -9 PID产生SIGKILL信号,表示立即结束进程。

Socket

前面提到的管道,消息队列,共享内存,信号量和信号都是在同一台主机上进行进程间通信,如果想要跨网络和不同主机上的进程进行通信,则需要用到socket。

实际上,Socket不仅可以跨网络和不同主机进行进程间通信,还可以在同一主机进行进程间通信。

Socket是操作系统提供给程序员操作网络的接口,根据底层不同的实现方式,通信方式也不同。

Socket的系统调用:

服务端和客户端初始化Socket,得到文件描述符
服务端调用bind,绑定IP和端口
服务端调用listen,进行监听
服务端调用accept,等待客户端连接
客户端调用connect,向服务端发起连接请求。(TCP三次握手)
服务端调用accept返回用于传输的Socket的文件描述符(和第一点得到的Socket不同)
客户端使用write写入数据,服务端调用read读取数据
客户端断开连接时会调用close,服务端也会调用close(TCP四次挥手)
这里要注意的是,调用accept,连接成功得到的Socket是用来传输数据的,而第一次初始化Socket是用来监听的,是两个不同作用的Socket。
原文链接:https://blog.csdn.net/OYMNCHR/article/details/124728256

 

标签:信号量,Socket,间通信,管道,进程,共享内存,服务端
From: https://www.cnblogs.com/tiange-137/p/17122464.html

相关文章

  • 期末复习——进程与线程
    MEMOPCB块:进程存在唯一唯一唯一!标志程序静态,进程动态每个进程有UID:用户ID,进程创建者的ID;通常大于500EUID:有效用户ID,表示进程对文件资源的访问权限;setuid:对二进制文......
  • 记一次系统进程数超限runtime/cgo: pthread_create failed: Resource temporarily un
    出现runtime/cgo:pthread_createfailed:Resourcetemporarilyunavailable错误​情况描述:dockerps查看运行的容器,发现提示一大堆的英文代码,其中提示一句​runtime/cgo......
  • Linux下查看某个进程文件的启动位置
    有时候我们在查看某个进程的时候,发现这个进程并没有完成的启动路径那我们需要对这个文件进行重启,就需要确认到这个程序的启动位置可以采用以下方法找到进程ID,进入【/proc/进......
  • 偶数科技为辽宁农信数字化进程添加新动能
    斗转星移,数据急剧膨胀2016年辽宁农信上线了基于关系型数据库的数据仓库,实现了各源系统的数据汇集。与此同时上线了大数据平台,实现了审计系统对各源系统贴源层数据的存储、整......
  • 进程同步和进程互斥
    进程同步和进程互斥1、什么是进程同步2、什么是进程互斥知识回顾......
  • execl 子进程创建踩坑
    execl函数:头文件:#include<unistd.h>功能:为进程重载0-3G的用户空间,可与fork函数搭配使用语法:intexecl("绝对路径",“标识符”,“需要的参数”(需要多少传入多少),NULL......
  • jmeter os进程取样器测试一段脚本
    os进程取样器执行本地命令我想执行一个本地的python代码window环境1.编写一段简单的python代码,命名pythontest.py存放在F:\ossample目录下name="hellopython"print......
  • 关闭 ReportCrash 进程防止CPU占用率过高 [MacBook]
    关闭ReportCrash的原因自己MacBookPro总是过载,机器很热。结果通过看进程top命令,看到ReportCrash占用了了过高的CPU,而且好像我用不上。于是乎,得关掉。然后,机器就......
  • Nginx - 深入理解nginx的处理请求、进程关系和配置文件重载
    概述Nginx的系统学习整理的第三篇博客,主要介绍nginx的应用场景和架构基础,以便更好的理解,再生产环境中进行性能调优。Nginx的三个主要应用场景1.静态资源服务,通过本地文......
  • 解决jeb不显示附加进程问题
    解决jeb不显示附加进程问题原因:之前比较懒adb直接用的模拟器的,但是测试的时候我用的是真机测试,死活就是不显示附加进程解决:https://dl.google.com/android/repository/pl......