进程间的通信

进程间的通信

进程间的通信实质上是通过计算机内核进行通信.在进程A与进程B进行通信时,计算机会在内核中开辟出一段缓冲区,然后进程A将通信数据拷至缓冲区,然后进程B再从缓冲区将数据取走,进而实现进程间的通信.

进程通信的方式

不同进程间的通信方式包含以下七种:
	1. 管道/匿名管道(Pip)
	2. 有名管道(FIFO)
	3. 信号(Signal)
	4. 消息队列(Message Queen)
	5. 共享内存(Share Memory)
	6. 信号量(Semaphore)
	7. 套接字(Socket)
	8. 客户端
1、管道/匿名管道(Pip)
1.1 管道的特点
管道是半双工的,数据只能单向流动,故当两个不同的进程A与进程B进行双向通信时需要建立两个管道,否则只能进行单向通信.
只能用于父子进程或者兄弟进程之间.
单独构成一种文件系统:  管道对于管道两端的进程来说就是一个文件,  但它不是普通的文件, 它不属于任何文件系统,而是自成一派,  单独构成一个文件系统,并且只存在内存中.
数据的读/写:管道的数据的读写与队列一样,  每次写入的数据都会写到管道缓冲区的末尾,  同时读数据时每次都是从管道缓冲区的头部读出.

进程通信模拟图

1.2 管道的实质
管道的实质是一个内核缓冲区,  进程以先进先出的方式顺序存取数据,  管道一端的进程顺序写入数据,管道另一端的进程则顺序读取数据.
该缓冲区可以看做是一个循环队列,读和写的位置都是自动增长的,不能随意改变,一个数据只能被读一次,读出来以后在缓冲区就不复存在了.
当缓冲区读空或者写满时,有一定的规则控制相应的读进程或者写进程进入等待队列,当空的缓冲区有新数据写入或者满的缓冲区有数据读出来时,就唤醒等待队列中的进程继续读写.
1.2 管道的局限
管道的局限由管道的性质所决定,如下所示:
1. 只支持单向数据流
2. 只能用于具有亲缘关系的进程之间
3. 没有名字
4. 管道的缓冲区大小是有局限的(管道制存在于内存中,  在管道创建时,为缓冲区分配一个页面大小)
5. 管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等
2、有名管道(FIFO)
由于匿名管道没有名字,故只能用于具有亲缘关系的进程之间,为了克服这个缺点,故而产生了有名管道。
2.1 定义
顾名思义,有名管道即管道在创建时与之关联一个路径名,以有名管道的文件的形式存在于文件系统中。假使A创建了一个有名管道,即使进程B与进程A不存在亲缘关系,只要进程B可以访问A进程创建的有名管道的路径,就能通过该管道进行通信。有名管道的名字存在于文件系统中,内容存在于内存中,同时有名管道和匿名管道一样,遵循先进先出的规则。
2.2 匿名管道和有名管道对比
1. 管道是特殊类型的文件,在满足先进先出的条件下可进行顺序读写操作,但不能进行定位读写操作。
2. 匿名管道是单向的,只能在具有亲缘关系的进程之间进行通信,有名管道以磁盘文件的形式存在,可以实现本机任意两个进程通信。
3. 匿名管道阻塞问题:匿名管道无需显示打开,创建时直接返回文件描述符,在读写时需要确定对方存在,否则将退出。如果向管道的一端写入数据,必须确定管道的另一端存在某个进程。如果写入的数据量过于庞大,超过管道的缓冲区大小,则写操作阻塞,当管道另一端的进程进行读操作时若管道缓冲区中数据为空,则读操作阻塞。
4. 有名管道阻塞问题:有名管道在打开时需要确定对方的存在,否则将阻塞。即当有一个以读方式打开的进程,那么必须有一个以写方式打开的进程,否则阻塞。另外,单个进程可以以读写方式(O_RDWR)打开进程,即自己读,自己写。
3、信号(Signal)
1. 通过信号通信无需知道另一个进程的状态。
2. 如果该进程当前并未处于执行状态,则信号就由内核保存起来,直到该进程回复执行并传递给它为止。
3. 如果一个信号被设置为组赛状态,则该进程会被延迟传递,直到该阻塞被取消才会传递给进程。
4. Linux系统中常用的信号量:
	SIGHUP:	用户从终端注销,所有运行的进程都将收到该信号。系统缺省状态下对该信号的处理方式是终止进程。
	SIGINT:程序终止信号。程序运行中按下Control+C将产生该信号。
	SIGQUIT:程序退出信号。程序运行中按下Control+\\将产生该信号。
	SIGBUS和SIGSEGV:进程访问非法地址。
	SIGFPE:运行过程中产生致命错误。如除零操作,数据溢出等。
	SIGKILL:用户终止进程执行信号。shell下执行kill -9发送该信号。
	SIGTERM:结束进程信号。shell下执行kill 进程pid发送该信号。
	SIGALRM:定时器信号。
	SIGCLD:子进程退出信号。如果其父进程没有忽略该信号也没有处理该信号,则子进程退出后将形成僵尸进程。
3.1 信号来源
信号是软件层次上对中断机制的一种模拟,是一种异步通信方式,信号可以在用户空间和内核之间传递,内核可以利用信号来通知用户空间的进程发生了那些系统事件,信号时间主要有两个来源:
硬件来源:硬件异常、无效的存储访问、用户按下control+C退出等。
软件终止:终止进程信号、其他进程调用kill函数、软件异常产生信号。
3.2 信号生命周期和处理流程
信号被某个进程产生,并设置此信号传递的对象(一般为对应进程的pid),然后传递给操作系统。
操作系统根据接收进程的设置(是否阻塞)而选择性的发送给接收者,如果接收者阻塞该信号(且该信号是可以阻塞的),操作系统将暂时保留该信号,而不传递,直到该进程解除了对此信号的阻塞(如果对应进程已经退出,则丢弃此信号),如果对应进程没有阻塞,操作系统将传递此信号。
目的进程接收到此信号后,将根据当前进程对此信号设置的预处理方式,暂时终止当前代码的执行,保护上下文(主要包括临时寄存器数据,当前程序位置以及当前CPU的状态)、转而执行中断服务程序,执行完成后在回复到中断的位置。当然,对于抢占式内核,在中断返回时还将引发新的调度。

图片来源网上

4、消息队列(Message Queen)
4.1 消息队列及其分类
消息队列是存在内核中的消息链表,每个消息队列由消息队列标识符表示。
与管道(匿名管道:只存在于内存中的文件;有名管道:存在于磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即操作系统重启)或者显示的删除一个消息队列时,该消息队列才会被真正的删除。
另外消息队列与管道不同的是:消息队列在某个进程忘一个队列写入消息之前不需要某个进程在该队列上等待消息的到达。
目前主要有两种类型的消息队列:POSIX消息队列和System V消息队列,  当前系统V消息队列被大量使用,  系统V消息队列是随系统内核持续的,  只有在系统内核重启或者人工删除时,该消息队列才会被删除
4.2 消息队列特点
1. 消息队列是消息的链表,存放在内核中,有消息队列标识符标识;
2. 消息队列允许一个或多个进程往消息队列写入或者读取消息;
3. 管道和消息队列的数据都是先进先出的原则;
4. 消息队列中的数据可以随机查询,消息不一定以先进先出的次序读取,也可以按消息的类型读取,比FIFO更有优势;
5. 消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺陷。
5、共享内存(share memory)
共享内存使得多个进程可以直接读取同一块内存空间,是最快的可用IPC形式,是针对其他通信机制运行效率较低设置的。
为了在多个进程间交换信息,内核专门留出一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读取这块内存而不需要进行数据的拷贝,从而大大提升效率。
由于多个进程共享同一块内存,因而需要依靠某种同步机制(如信号量)来达到进程间的同步和互斥。

图片来源网上

6、信号量(share memory)
信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。为了获得共享资源,进程需要执行如下操作:
1.	创建一个信号量:要求调用者指定一个初始值,对于二值信号量来说可以是0也可以是1。
2.	等待一个信号量:该操作会测试该信号量的值,如果小于0,就阻塞,通常也称为P操作。
3.	挂出一个信号量:该操作将信号量的值加1,也通常称为V操作。
为了正确的实现信号量,信号量值的测试及减1操作应当是原子操作。为此,信号量通常在内核中实现。
在Linux系统环境中,有三种信号量:
1.	POSIX(可移植性操作系统接口)有名信号量(使用POSIX IPC名字标识);
2.	POSIX基于内存的信号量(存放在共享内存区中);
3.	System V信号量(在内核中维护)。这三种信号量均可用于进程或者线程间的同步。 

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

6.1 信号量与普通整型变量的区别
1.	信号量是非负整型变量,除了初始化之外,它只能通过两个标准原子操作:wait(semap) , signal(semap) 来进行访问;
2.	操作也被成为PV原语(P来源于荷兰语proberen"测试",V来源于荷兰语verhogen"增加",P表示通过的意思,V表示释放的意思),而普通整型变量则可以在任何语句块中被访问;
6.2 信号量与互斥量之间的区别
6.2.1 同步与互斥的基本定义
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。
在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源
6.2.2 区别
1. 互斥量用于线程的互斥,信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。
2. 互斥量值只能为0/1,信号量值可以为非负整数。也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量时,也可以完成一个资源的互斥访问。
3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
7、套接字(Socket)
套接字是一种通信机制,凭借这种机制,客户/服务端(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。

在这里插入图片描述

套接字是支持TCP/IP的网络通信的基本单元,可以看作是不同主机之间进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中相关函数来完成通信过程。
7.1 套接字特性
套接字特性有三个属性决定,他们分别是:域、端口号、协议类型,以下分别对此进行介绍:
7.1.1 套接字的域
它指定套接字通信中使用的网络介质,最常见的套接字域有两种,一是AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。
另一个域AF_UNIX,表示UNIX文件系统,它就是文件输入/输出,而它的地址就是文件名。
7.1.2 套接字的端口号
每一个基于TCP/IP网络通讯的程序(进程)都被赋予了唯一的端口和端口号,端口是一个信息缓冲区,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数,范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于256的端口号保留给标准应用程序,比如pop3的端口号就是110,每一个套接字都组合进了IP地址、端口,这样形成的整体就可以区别每一个套接字。
7.1.3 套接字协议类型
1.	流套接字,流套接字在域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
2.	数据报套接字,它不需要建立连接和维持一个连接,它们在域中通常是通过UDP/IP协议实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并不一定需要总是要建立和维持一个连接。
3.	原始套接字,原始套接字允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW。
7.1.4 原始套接字与标准套接字的区别
原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据,必须使用原始套接字。
7.2 套接字通信的建立

在这里插入图片描述

7.2.1 服务端
1.	首先服务端应用程序用系统调用socket来创建一个套接字,他是系统分配给该服务进程的类似文件描述符的资源,他不能与其他进程共享。
2.	然后,服务进程会给套接字取一个名字,我们使用系统调用bind来给套接字命名。然后服务端进程就等待客户连接到这个套接字。
3.	接下来系统调用listen来创建一个队列并将其用于存放来自客户端的进入连接。
4.	最后,服务器通过系统调用accept来接收客户的连接。他会创建一个与原有的套接字不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原有的套接字)被留下来继续处理来自其他客户端的连接(建立客户端和服务端用于通信的流,进行通信)。
7.2.1 客户端
1.	客户应用程序首先调用socket创建一个未命名的套接字,然后将服务器的命名套接字作为一个地址调用connect与服务端创建连接。
2.	一但连接创立,我们就可以像使用底层文件的描述符那样用套接字来实现双向通信(通过流进行数据传输)。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值