- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
多个进程之间需要协同来完成某项任务:
eg
cat log.txt | gerp "hehe"
具备通信的的前提条件:
因为进程具有独立性,所以不能在两个进程各自的区域来进行通信,就好比警察和黑帮的卧底,需要用纸条来通信,所以不能在各自的地盘,所以OS需要给需要通信的进程提供一个内存空间 。
并且两个进程之间都可以看到一个公共的资源(空间) 。
操作系统的很多模块都可以提供公共空间 。
管道通信 。
- 匿名管道
- 命名管道
System V IPC 。
- System V 消息队列
- System V 共享内存
- System V 信号量
POSIX IPC 。
- 消息队列
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
对于文件系统来说,被打开的文件在文件描述符表里有对应的fd (文件描述符) 。
当一个进程fork()后,子进程会拷贝父进程的大部分资源,其中就包括文件struct files_struct,当然,**file* fd_array **也拷贝过去,即文件描述符表 。
所以子进程能指向和父进程同一个被打开的文件所以子进程创建后,打开的文件和父进程指向的是同一个文件 。
此时就初步具备了通信的条件,这个空间是由文件系统提供的,文件在磁盘里 。
但是,文件系统需要访问外设(即磁盘),所以访问速度相对较慢 。
有一种内存级的文件,他没有对应的磁盘文件,但是有自己的file结构体,这个实现是操作系统本身用联合体实现的,这个细节实现是OS去操作的.
对于每个struct file都有 。
1.file的操作办法 2. 内核缓冲区 。
对于一个struct file,可以不指向磁盘中的文件,因为这个实现是操作系统来实现的 。
所以操作系统在内存中创建一个不指向磁盘中任何文件的struct file,即只有一个结构体,这个结构体里当然也具备了1.file的操作办法 2. 内核级缓冲区,所以进程之间可以通过这个匿名文件的缓冲区来进行通信 。
当父进程打开一个内存级文件的时候,fork子进程,子进程也具备了指向该内存级文件,所以父子进程可以用这个内存级文件来进行通信,不需要访问磁盘就可以完成,所以速度就会大大提升,这个文件没有名字,所以叫做匿名管道 。
如下图 。
管道在生活中就是用来单向传输的,一头输入一头只输出 。
管道需要读和写,所以一个父进程需要同时具备读和写权限的属性才能fork子进程,要不然子进程没办法进行读或者写 。
但是又不能父子进程两个都写,或者都读,只能一方写,一方读 。
所以创建过程如下:
fd
,如果没关,万一没关可能会被不小心访问到⭐管道是一个父进程分别以读和写方式打开一个内存级文件,并通过fork创建一个子进程,各自再关闭对应的读写端,进而形成一条通信信道,这样的信道是基于文件的,所以叫做:管道 。
匿名管道 :目前只能用来进行父子进程间通信 。
#include <unistd.h>
//功能:创建一无名管道
//原型
int pipe(int fd[2]);
//输出型参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
联想记忆法 : 1. fd[0]:0比作嘴巴,读东西,读端 。
2. fd[1]: 1比作笔,写东西,写端
在fork子进程后,父子进程是读还是写,那么就关闭不用的一个,fork()之后各自关掉不用的描述符 。
读慢,写快 。
写的速度>读的速度,管道也是有最大容量的 。
所以当管道被写满时,将不在继续写,直至读端读走数据有可以写的空间,写端才继续写 。
读快,写慢 。
读的速度>写的速度 。
因为读速度大于写速度,所以当读端读完管道内的内容时,此时已经没有内容可读了,那么进程将阻塞在read函数这里,等待写端写,直至管道内有数据可继续读 。
写端关闭,读端不关闭 。
当管道写端关闭时,读端读完管道内的数据时,如果再次去读没有数据的管道会返回0,相当于读到了EOF 。
读端关闭,写端不关闭 。
读关闭,操作系统将给进程法信号,终止写端,因为不需要读的话,就是浪费系统资源,操作系统会强制终止写端 。
1.mkfifo函数创建命名管道 。
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname,mkde_t mode);
pathname : 要创建命名管道的目录和文件名 。
返回值 。
成功返回 0 ,失败返回 -1
命名管道的文件类型是p 。
2.命名管道的原理 。
在进程中打开命名管道文件的方法跟普通文件一样 。
struct file
,然后将其地址放到task_struct
中的files_struct
中的文件描述符表中struct file
3.两个无血缘进程间的通信 。
让两个进程看到同一份命名管道,然后分别选择一个读和写 。
注意细节:当只有一端打开命名管道时,eg:只打开读端,另一端还没就绪,此时打开的一端会阻塞自己,等待另一端就绪 。
共享内存区是最快的IPC形式,一旦这个shm与进程地址空间映射,那么无需通过内核进行通信,直接通过一个内存进行通信,但是由于共享内存只能在本地进行多个进程间通信,所以就慢慢的被淘汰掉了了 。
key
,生成一个独一无二的key
,其他进程(人)进来需要key
,创建共享内存时候要传这个key
就好比开个房间如上图,通过页表映射到各自的进程地址空间,从而实现两个进程可以实现进程间通信 。
key*
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
//pathname放一个指定的路径即可,proj_id指定一个数值即可,但是记得另一个进程对应得这两个参数也要一样
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
//key即上边得Key , size为开辟共享内存得大小单位是字节
参数:shmflg 是一个用标志位代表的一个参数有两个IPC_CREAT,IPC_EXCL 。
IPC_CREAT : 如果没有那么创建共享内存,如果已经有了,那么返回共享内存的shmid 。
IPC_EXCL : 该宏必须和IPC_CREAT一起使用,否则没有意义。当shmget取IPC_CREAT|IPC_EXCL时,表示如果发现信号集已经存在,则返回-1,错误码为EEXIST.
创建时必须加上创建共享内存的权限码0600 。
//1.创建时一般用下边这个
int shmid=shmget(key,4096,IPC_EXCL|IPC_CREAT|0600);
//2.获取时用下边的这个
int _shmid=shmget(key,4096,IPC_CREAT);
返回值 :成功返回共享内存的shmid,失败返回-1 。
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数: hm_addr指定共享内存连接到当前进程中的地址位置,通常为空(nullptr),表示让系统来选择共享内存的地址.
shm_flg是一组标志位,通常为0 。
int shmdt(const void *shmaddr);
参数shmaddr是shmat()函数返回的地址指针,调用成功时返回0,失败时返回-1. 。
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
- IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
- IPC_RMID:删除共享内存段
- 返回值 : 失败返回 -1
为什么要让不同的进程看到同一份公共资源呢---->为了不同进程之间进行通信,协同工作等------>那么就让不同的进程看到同一份资源------->提出产生公共资源的方法----->过程中遇到问题------>数据不一致问题,比如还没有写完另一边就开始读取了 。
临界资源 : 被保护起来的公共资源被称作临界资源(临界资源占少数,因为大部分资源都是各自进程自身的,只有进程要通信并且防止被打扰才会进行保护,所以临界资源在这个条件下占少数) 。
临界资源(内存,文件,网络等)是要被使用的,如何被进程使用呢?进程存在对这部分资源的使用方法代码,由这部分代码来实现,那么这部分代码区域被称作临界区 ,其他区域则被称作非临界区 。
如何保护:互斥和同步 。
原子操作 : 对于一件事情 , 要么就一开始就不做,要么做了就做完 。
对于共享资源的使用:1.作为一个整体 2.拆分成若干个部分使用 。
所有的进程在访问公共资源的前提下,需要先申请信号量------>所以必须进程都能看到信号量,那么信号量也是一个公共资源----->所以信号量也要保证自己的安全------->所以信号量进行++或者- -操作是原子性的 。
那么, 对于信号量获取资源进行信号量--的操作被称为P操作 。
对于信号量回收资源进行信号量++的操作被称为V操作 。
系统的IPC资源常见的有:消息队列,共享内存,信号量等 。
这些资源都包括了两个结构体:1.自身的结构体例如struct shm_ds或者sem_ds 2.struct ipc_prem 。
这些资源是由OS统一管理的,OS会创建一个数组 : ipc_prem *prems[ ];,由这个数组统一管理ipc资源 。
shm_ds
最后此篇关于进程间通信的文章就讲到这里了,如果你想了解更多关于进程间通信的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
大多数语言都支持双向进程通信。例如,在 Python 中,我可以(草率地)执行以下操作: >>> from subprocess import * >>> p = Popen('nslookup',
致力于使用 C++ 在 arduino 和 PC (Win 7) 之间进行通信。使用 WriteFile 和 ReadFile 创建通信或简单地发送或接收数据没有问题。但是当我想以某种方式“协调”沟通
我们正在开发一个基于微服务的应用程序。它们将使用 Helm Package Manager 部署到 kubernetes,并且它们都存储了自己的存储库和 helm chart。以下是我们微服务的名称。
我正在开发一个大型 MVVM 应用程序。我为此使用了 MVVM 轻量级工具包。该应用程序就像一个带有后退和前进按钮的网络浏览器。主视图是一个用户控件。我在主视图用户控件中放置了后退和前进按钮。主视图又
我在 java 和 freepascal(lazarus) 应用程序之间的通信有问题。我使用套接字。它们正确连接。一切都很顺利,直到我想从一个应用程序向另一个应用程序发送一些东西。在java而不是“a
我已经使用客户端套接字和服务器套接字使用C#编写了群聊。 当我使用VS 2017在自己的PC中运行程序(服务器和客户端)时,客户端和服务器之间的通信工作正常。 当我在笔记本电脑中运行客户端程序,并在自
Kubernetes 中两个不同 Pod 之间的通信是如何发生的? 就我而言,我有两个 Pod:前端和后端,它们都有不同的容器。 我希望我的前端 pod 与后端 pod 通信,但我不想使用后端 pod
我正在尝试在浏览器中嵌入的 flash 实例与在 C# WinForms 应用程序中运行的 flash 实例之间进行通信...我收到一个编译错误,内容为: 1119 Access of possibl
鉴于网络上缺乏信息,请问一个问题:我要在 Android 中创建一个应用程序,使用一个数据库应用程序 rails 。为此,我需要一个手动 session 。所以如果有人准备好了示例/教程显示通信 an
我正在编写一个应用程序,它将通过 MySQL 数据库对用户进行身份验证。我已经用 Java (android) 编写了它,但现在正在移植到 Windows 手机。 PHP 文件使用 $get 然后回显
是否可以通过互联网在两个不同设备上的两个不同应用程序之间建立通信。我想从设备 A 上的应用程序点击一个设备 B 上的应用程序,然后从设备 B 上的应用程序获取数据到设备 A 上的应用程序。如果可能,如
这是脚本: 它被放置在其他网站上。 com 并显示一个 iframe。如果有人点击 iframe 中的某个内容,脚本应该将一个 div 写入 othersite 。 com. 所以我的问题是如何做到
你好我是 php 的新手,我用 c++ 编写了整个代码并想在 php 中使用这段代码。所以我为我的代码制作了 dll 以使用它。但是我不能在 php 中使用这个 dll,可以谁能给我完整的代码来使用
我确定之前已经有人问过(并回答过)此类问题,所以如果是这样,请将我链接到之前的讨论... 在 C++ 中,假设我有一个 ClassA 类型的对象,其中包含一个 ClassB 类型的私有(private
我正在尝试使用 ATmega32 进行串行通信。首先,我使用 RS232,使用 USB-to-RS232 建立使用串行终端的接收和传输(在我的例子中是 tera 术语)。无论我从串行终端 Atmega
我找不到适用于 Ruby 的 SSL 实现。 我的部分项目需要服务器和客户端之间的安全通信链接,我希望为此使用 SSL 以创建安全 session 。 谢谢 最佳答案 如果你使用 Ruby 1.9.x
我正在尝试在客户端/服务器之间进行 SSL 通信。 到目前为止,我已经从 keystore 创建了 java.security.cert.X509Certificate。接下来我应该怎么做才能使这次沟
我在与 Windows 上的 USB 设备 通信时遇到问题。我不能使用 libusb 或 WinUSB,因为我有一个特定的驱动程序(Silabs USB 到 UART,这是一个 USB 到串口的桥接器
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我发现 xcom 实际上是将数据写入数据库并从其他任务中提取数据。我的数据集很大,将其腌制并写入数据库会导致一些不必要的延迟。有没有办法在不使用 xcom 的情况下在同一 Airflow Dag 中的
我是一名优秀的程序员,十分优秀!