进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
IPC 对象的持续性分为三种:随进程,随内核和随文件系统

  • 随进程持续的 IPC 对象:一直存在到打开着 IPC 对象的最后一个进程关闭该对象为止,管道、FIFO 随进程
  • 随内核持续的 IPC 对象:一直存在到内核重新自举或者显示删除 IPC 对象为止,Posix 消息队列随内核
  • 随文件系统:一直存在到显示删除IPC对象为止

1. 管道

管道分为 PIPE(无名管道)和 FIFO(命名管道)两种,除了建立、打开、删除的方式不同外,这两种管道几乎是一样的。他们都是通过内核缓冲区实现数据传输。

PIPE 用于相关进程之间的通信,例如父进程和子进程,它通过 pipe() 系统调用来创建并打开,当最后一个使用它的进程关闭对他的引用时,PIPE 将自动撤销。

  1. 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  2. 匿名管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
  3. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。

FIFO 即命名管道,在磁盘上有对应的节点,但没有数据块——换言之,只是拥有一个名字和相应的访问权限,通过 mknode() 系统调用或者 mkfifo() 函数来建立的。一旦建立,任何进程都可以通过文件名将其打开和进行读写,而不局限于父子进程,当然前提是进程对 FIFO 有适当的访问权。当不再被进程使用时,FIFO 在内存中释放,但磁盘节点仍然存在。

  1. 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
  2. FIFO 可以在无关的进程之间交换数据,与无名管道不同。

管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据,该缓冲区可以看做一个循环队列,读和写的位置都是自动增加的,一个数据只能被读一次,读出以后再缓冲区都不复存在了。当缓冲区读空或者写满时,有一定的规则控制相应的读进程或写进程是否进入等待队列,当空的缓冲区有新数据写入或慢的缓冲区有数据读出时,就唤醒等待队列中的进程继续读写。

2. 消息队列 MessageQueue:

消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

  1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
  2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
  3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

消息队列与管道通信相比,其优势是对每个消息指定特定的消息类型,接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。

可以把消息看做一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程可以从消息队列中读取消息。

进程间通过消息队列通信,主要是:创建或打开消息队列,添加消息,读取消息和控制消息队列。

3. 共享存储 SharedMemory:

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

  1. 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
  2. 因为多个进程可以同时操作,所以需要进行同步。
  3. 信号量 + 共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

共享内存允许两个或多个进程共享一个给定的存储区,这一段存储区可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取错做读出,从而实现了进程间的通信。
采用共享内存进行通信的一个主要好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝,对于像管道和消息队里等通信方式,则需要再内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次:一次从输入文件到共享内存区,另一次从共享内存到输出文件。
共享内存有两种实现方式:
1、内存映射
内存映射 memory map 机制使进程之间通过映射同一个普通文件实现共享内存,通过 mmap() 系统调用实现。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read/write 等文件操作函数。

例子:创建子进程,父子进程通过匿名映射实现共享内存。

分析:主程序中先调用 mmap 映射内存,然后再调用 fork 函数创建进程。那么在调用 fork 函数之后,子进程继承父进程匿名映射后的地址空间,同样也继承 mmap 函数的返回地址,这样,父子进程就可以通过映射区域进行通信了。
2、共享内存机制
IPC 的共享内存指的是把所有的共享数据放在共享内存区域(IPC shared memory region),任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面。

和前面的 mmap 系统调用通过映射一个普通文件实现共享内存不同,UNIX system V共享内存是通过映射特殊文件系统 shm 中的文件实现进程间的共享内存通信。

例子:设计两个程序,通过 unix system v 共享内存机制,一个程序写入共享区域,另一个程序读取共享区域。

分析:一个程序调用 fotk 函数产生标准的 key,接着调用 shmget 函数,获取共享内存区域的 id ,调用shmat 函数,映射内存,循环计算年龄,另一个程序读取共享内存。

4. 信号量 Semaphore:

信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

  1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
  3. 每次对信号量的 PV 操作不仅限于对信号量值加1或减1,而且可以加减任意正整数。
  4. 支持信号量组。

5. 套接字 Socket:

socket,即套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。也因为这样,套接字明确地将客户端和服务器区分开来
套接字的特性由3个属性确定,它们分别是:域、类型和协议。

  1. 套接字的域
    它指定套接字通信中使用的网络介质,最常见的套接字域是 AF_INET,它指的是 Internet 网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的 IP 地址和端口来指定一台联网机器上的某个特定服务,所以在使用 socket 作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。另一个域 AF_UNIX 表示 UNIX 文件系统,它就是文件输入/输出,而它的地址就是文件名。

  2. 套接字类型
    因特网提供了两种通信机制:流(stream)和数据报(datagram),因而套接字的类型也就分为流套接字和数据报套接字。这里主要讲流套接字。
    流套接字由类型 SOCK_STREAM 指定,它们是在 AF_INET 域中通过 TCP/IP 连接实现,同时也是AF_UNIX 中常用的套接字类型。流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
    与流套接字相对的是由类型 SOCK_DGRAM 指定的数据报套接字,它不需要建立连接和维持一个连接,它们在 AF_INET 中通常是通过 UDP/IP 协议实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失、复制或错乱到达,UDP 不是一个可靠的协议,但是它的速度比较高,因为它并一需要总是要建立和维持一个连接。

  3. 套接字协议
    只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常只需要使用默认值。

6. 信号 Sinal ):

信号,是 Linux 中向进程发送的消息,接收到该信号的进程会相应地采取一些行动,即通过软中断的方式来响应这个信号,触发一些事先指定或特定的事件。进程之间可以互相通过系统调用kill来发送信号,内核也可以因为内部事件而给进程发送信号,通知进程发生了某件事件。

信号的产生
  1. 由硬件产生,如从键盘输入 Ctrl+C 可以终止当前进程
  2. 由其他进程发送,如可在 shell 进程下,使用命令 kill -信号标号 PID,向指定进程发送信号。
  3. 异常,进程异常时会发送信号
信号的处理
  1. 信号是由操作系统来处理的,说明信号的处理在内核态。
  2. 信号不一定会立即被处理,此时会储存在信号的信号表中。
信号有三种处理方式
  1. 忽略
  2. 默认处理方式:操作系统设定的默认处理方式
  3. 自定义信号处理方式:可自定义信号处理函数

Java 多线程 - 2 - 进程间通信方式相关推荐

  1. Java 多线程的基本方式

    Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

  2. Java多线程的实现方式-Thread 类,Runnable 接口

    在 Java 的 JDK 开发包中,已经自带了对多线程技术的支持,可以方便地进行多线程编程.实现多线程编程的方式主要有两种:一种是继承 Thread 类,另一种是实现 Runnable 接口.下面详细 ...

  3. java多线程的实现方式_Java 多线程(一)——多线程的实现方式

    一.前言 Java 异常的处理方式与自定义异常 我们已经讲完了,从今天开始我们来学习多线程. 二.与多线程相关的概念 2.1.并发与并行并发:指两个或多个事件在同一个时间段内发生,具体如下图所示: 并 ...

  4. java 多线程两种方式_JAVA多线程实现的两种方式

    java多线程实现方式主要有两种:继承Thread类.实现Runnable接口 1.继承Thread类实现多线程 继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了 ...

  5. Java 多线程加锁的方式总结及对比

    前言 Java多线程可以通过: synchronized关键字 Java.util.concurrent包中的lock接口和ReentrantLock实现类 这两种方式实现加锁. Lock 和 syn ...

  6. 一篇文章认识4种Java多线程的创建方式

    Java4种多线程的创建: 什么是程序? 什么是进程? 什么是线程? 并行与并发: 那么JAVA多线程实现方式: (1)继承Thread类实现多线程: (2)实现Runnable接口方式实现多线程: ...

  7. java多线程的实现方式_JAVA多线程实现的三种方式

    最近在做代码优化时学习和研究了下JAVA多线程的使用,看了菜鸟们的见解后做了下总结. 1.JAVA多线程实现方式 JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用E ...

  8. Java多线程的实现方式 --转载

    最近在做代码优化时学习和研究了下JAVA多线程的使用,看了菜鸟们的见解后做了下总结. 1.JAVA多线程实现方式 JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用E ...

  9. JAVA单线程以及java多线程的实现方式

    1.java单线程的实现 public class SingletonThread {@SuppressWarnings("static-access")public static ...

最新文章

  1. TensorFlow——入门基础
  2. Hadoop之父Doug Cutting
  3. 语言堆栈入门——堆和栈的区别
  4. python格式化输出的三种形式
  5. rhel 7.2 安装mysql_在rhel7.2下源码安装mysql-5.6.35
  6. 修改类名后依旧按照原先的类名进行加载
  7. 云计算体系结构中soa构建层_云计算的服务模式及技术结构
  8. 掌握MySQL数据库这些优化技巧,事半功倍!
  9. fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64
  10. 「12」你们啊,naive!——朴素贝叶斯谈笑录
  11. php上搭建dvwa,使用phpstudy在windows上搭建DVWA
  12. 决策树C4.5算法对ID3算法的改进
  13. Thinkphp 6.0商城系统,B2C商城系统全新UI
  14. 《疯狂java讲义》第17章 网络编程
  15. 数据挖掘工具weka之weka包的安装
  16. html字体图标显示不出来,h5页面字体图标显示不正常
  17. 光驱刻录空盘提示函数不正确
  18. Linux系统下安装screen
  19. 网易互娱AI Lab视频动捕技术iCap被CVPR 2022接收!
  20. C#和西门子PLC使用Udp通信

热门文章

  1. 如何在Ubuntu 16.04上增加Swap分区
  2. 使用chatgpt实现微信聊天小程序(秒回复),github开源(附带链接)
  3. 互联网摸鱼日报(2023-03-10)
  4. 找工作必备书籍推荐-----软件开发
  5. 自动驾驶、人工智能将把你的未来生活变成什么样?
  6. MySQL索引学习漫画
  7. Python 动画没有秘密
  8. JavaScript之操作符
  9. 寄存器r0-r15含义
  10. dp、dpi、px的区别?