- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在操作系统中,进程间通信是指不同进程之间进行信息共享、数据传输和消息通知等交互的过程。每个进程在创建时都有自己独立的虚拟地址空间,但它们共享内核空间。因此,要实现进程间的通信,必须通过内核来进行中介,如下图所示:
在Linux系统中,提供了多种进程间通信的机制,包括管道、消息队列、共享内存、信号量、信号、套接字等。这些机制允许进程之间共享数据、传输消息以及进行进程间的同步与通信。下面我们详细讲解下.
管道是一种进程间通信机制,它可以将一个进程的输出直接作为另一个进程的输入。在Linux系统中,管道可以用于将命令的输出传递给另一个命令进行处理.
ps -ef |grep java
使用Linux系统练手的时候,想必大家都是用这样的一种命令查看java进程,命令中的 | 就是管道命令,但是这个是匿名管道,用完了就销毁,匿名管道只能在有父子关系的进程之间进行通信。他的功能也很好理解,一个进程的输出直接作为另一个进程的输入,所以才能只展现java进程,所以他的传输方式是单向传输.
那么既然有匿名管道,就有命名管道,被叫做 FIFO ,因为数据是先进先出的传输方式。命名管道具有读写两个端口,进程可以通过打开管道的文件来进行读取或写入。当一个进程写入数据到管道时,另一个进程可以从管道中读取数据.
在使用命名管道前,先需要通过 mkfifo 命令来创建,并且指定管道名字:
$ mkfifo myPipe
myPipe 是管道的名称,在 Linux 中一切皆文件的原则下,管道也以文件的形式存在。我们可以使用 ll 命令查看一下,该文件的类型是 p,表示为管道(pipe).
接下来,我们将数据写入名为 myPipe 的管道中:
在执行完写入操作后,你可能会发现命令执行后一直停留在那里。这是因为管道中的数据没有被读取,只有当管道中的数据被完全读取后,命令才能正常退出。因此,我们需要执行另一个命令来读取管道中的数据:
可以观察到,管道中的内容已经被成功读取并打印在终端上,另外,echo命令也正常退出了.
从中我们可以得知,匿名管道的通信范围限定在具有父子关系的进程之间。由于管道本身没有实体,也就是没有管道文件,所以只能通过fork来复制父进程的文件描述符,以实现进程间的通信。(fork是一个操作系统调用,用于创建一个新的进程。当调用fork时,操作系统会复制当前进程的副本) 。
在shell中执行A | B命令时,A进程和B进程都是由shell创建的子进程。A和B之间不存在父子关系,它们的父进程都是shell.
此外,对于命名管道,它可以在不相关的进程之间进行通信。这是因为命名管道事先创建了一个特定类型的设备文件,在进程中只需要使用该设备文件,就可以实现进程之间的通信.
消息队列是一种进程间通信的机制,它相比于管道具有更高的效率和灵活性。消息队列是通过在内核中创建一个消息链表来实现的,进程可以将数据放入消息队列中,然后其他进程可以从队列中读取这些数据.
例如,当进程A需要向进程B发送消息时,进程A将数据放入B进程对应的消息队列后即可正常返回。而进程B可以在需要时去读取数据。同样地,当进程B需要向进程A发送消息时,也可以按照相同的方式进行操作.
与管道不同的是,消息队列是有格式的,每个消息体都是固定大小的存储块,进程在读取数据时需要约定好消息体的数据类型。消息队列的优势在于可以支持进程间的异步通信,发送方和接收方不需要同时运行,消息可以在队列中等待对方读取。不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除.
消息队列的生命周期与内核相关,如果没有显式地释放消息队列或关闭操作系统,消息队列将一直存在。而管道的生命周期是随着进程的创建和结束而动态建立和销毁.
然而,消息队列也存在一些缺点。由于数据在用户态和内核态之间进行拷贝,消息队列通信过程中存在一定的开销。当进程将数据写入消息队列时,需要将数据从用户态拷贝到内核态;而另一个进程从消息队列中读取数据时,需要将数据从内核态拷贝到用户态。这种数据拷贝开销会影响通信的效率.
共享内存是一种高效的进程间通信机制,它允许多个进程共享同一块内存区域,避免了数据的拷贝过程,提高了通信速度.
在共享内存机制中,操作系统将一块共享内存区域映射到多个进程的虚拟地址空间中,使得它们可以直接访问同一块物理内存。这样,一个进程对共享内存的写入操作,其他进程可以立即看到更新后的数据,而不需要进行数据的拷贝传输.
由于共享内存不进行数据拷贝,因此在进程间通信的过程中,它具有较低的开销和较高的传输速度。然而,共享内存机制需要通过同步机制来保证多个进程之间的数据一致性,以免出现竞争条件和数据不一致的问题.
本篇文章总结了进程间通信的三种常见机制:管道、消息队列和共享内存。它介绍了每种机制的特点、优缺点以及适用场景。管道适用于父子进程之间的通信,但只能在有亲缘关系的进程之间使用。消息队列可以用于异步通信,并且支持多个进程之间的通信,但是消息的格式需要事先定义。共享内存是一种高效的通信方式,可以实现多个进程共享同一块内存区域,但需要处理进程间的同步和互斥。根据实际需求,可以选择合适的机制进行进程间通信.
下一篇文章将继续探讨信号量、信号和套接字的知识点! 。
最后此篇关于深入探讨进程间通信的重要性:理解不同的通信机制(上)的文章就讲到这里了,如果你想了解更多关于深入探讨进程间通信的重要性:理解不同的通信机制(上)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 GGally::ggpair 的最新版本中,相关值用 * 显示,如下图所示。我想删除 *s 并保留相关值。 我看过 ggpairs 代码,但它对我来说并不明显。 GGally::ggpairs(d
在 GGally::ggpair 的最新版本中,相关值用 * 显示,如下图所示。我想删除 *s 并保留相关值。 我看过 ggpairs 代码,但它对我来说并不明显。 GGally::ggpairs(d
我正在尝试使用在 weka 库中实现的 SVM 分类来对一些数据进行分类。我的分类代码如下所示: BufferedReader reader = new BufferedReader(new File
我已经为 jdbm 构建了 Lucene Directory 实现,一个嵌入式Java数据库。 Directory API 的一部分是与"file"修改日期相关的两个方法:touchFile 和 fi
我的任务是编写一个函数,将文件中单词的长度与整数进行比较,然后返回所有符合该大小的单词。我得到的答案几乎相同,除了我没有像他们那样包含 string.strip() : def get_words(d
xgb.importance 命令返回由 f score 衡量的特征重要性图。 这个f分数代表什么,它是如何计算的? 输出: Graph of feature importance 最佳答案 这是一个
有一个二元分类问题:如何获得 Ranger 模型变量的 Shap 贡献? 示例数据: library(ranger) library(tidyverse) # Binary Dataset df %
如今 servlet 在哪里使用? 我知道 servlet 是在面向请求/响应的服务器(例如支持 Java 的 Web 服务器)中运行的模块。但是现在我没有听到任何人使用 servlet。这可能是因为
我是一名优秀的程序员,十分优秀!