14-IPC通信基本
进程间通信(IPC:Inter-Process Communication)
1. 为什么需要进程间通信
比如,当我的程序是多进程协同工作时,进程间基本都会涉及到数据共享。
如何实现进程间数据的共享?
使用进程间通信来实现数据共享,也就是说进程间通信的目的,就是为了实现进程间数据共享的。
2. 进程间通信有什么意义
我们在实际开发中,大多数情况下,程序所涉及的都是单进程的情况,很少是多进程的。对于单进程的应用程序
来说,由于程序内部不存在多进程的情况,所以也就基本不存在进程间数据共享的需求,所以不会用到进程间通信。
本文介绍IPC都是C接口的,如果java等其它语言要实现多进程时,必须调用该语言的函数接口来实现。
(1)有助于理解其它OS的进程间通信
其实,所有OS的进程间通信,采用的基本都是类似的实现机制,所以知道了Linux的进程间通信后,相当于也
了解了其它OS的进程间通信。
(2)加深对进程的理解,帮助后续对比学习c线程
还是以信号量为例,c的线程同样有信号量这个东西,其原理与本章的进程信号量的原理也是类似的
(3)有助于理解java等语言写程序的IPC
我们使用java等语言来编写程序时,虽然一般也是单进程的,但是java也提供了实现多进程的
函数接口(类接口),当java程序涉及多进程时,往往也会涉及到进程间通信,所以java也提供了进程间
通信的函数接口,java的进程间通信机制有:
1)信号
2)管道(有名、无名)
3)消息队列
4)共享内存
5)信号量
Linux OS所提供的、c接口的进程间通信机制也分为:
1)信号
2)管道(有名、无名)
3)消息队列
4)共享内存
5)信号量
疑问:为什么会一样呢?
因为java实现多进程以及进程间通信的函数接口,其实还是通过调用OS提供的接口来实现的,所以一样
是正常的
不仅仅是java进程,对于理解java线程也是很有帮助的,比如java线程里也有信号量这个东西,它的工
作原理与进程信号量的原理也是类似的。
我们这里需要注意一点,并不是所有语言的库,都有提供“进程控制”和“进程间通信”的库接口,比如C标
准库就没有。
所以如果你的C程序在windows和Linux下想要实现“进程控制”和“进程间通信”的话,必须调用系统API
或者说该系统自己特有C库(不是标准c库)
4. 进程间的数据共享
(1)如果OS不提供专门的进程间通信机制的话,进程间实现数据共享容易吗?
答:不容易,为什么不容易呢?
如果进程空间之间有可以共享的交叠空间的话,进程间可以通过这个交叠的空间,很容易的就能实现
数据共享。
这就好比两个独立的房间,在这个两个房间之间有一个共享空间(交叠空间),这两个房间之间就可以
通过这个共享空间来交换物品。
但是实际情况是,每个进程的进程空间是完全独立的,进程空间没有任何的交叠,所以实现数据共享的
难度很高。
(2)为什么进程空间是完全独立的
进程空间完全独立,会使得进程间共享数据很困难
1)什么是进程空间
其实就是程序运行的内存空间,不过OS有提供虚拟内存时,我们所说的进程空间,指的都是虚拟内存空间。
疑问:为什么进程空间指的不是程序所运行的真实物理内存空间呢?
答:虚拟内存是基于物理内存实现的,说虚拟内存时,本身就包含了虚拟内存所对应的底层物理内存空间
2)虚拟地址与物理地址
虚拟内存有自己的虚拟地址(就是一些编号),之所以叫虚拟地址,是因为这些地址并不对应真实物理
内存。
CPU取指运行时,PC是通过虚拟地址来取指的,但是我们的程序指令肯定是放在了真实的物理内存上的,
所以虚拟地址最终会被转换为物理地址,然后到真实的物理内存中取出指令,再供CPU执行
3)每一个进程空间的虚拟地址都是一样的吗?
当然,如果不一样的话,管理起来会非常的麻烦。
对于32位的OS来说,虚拟内存的虚拟地址的编码范围为:
4G-1:11111111 11111111 11111111 11111111 (2(32)-1)
4G-2:11111111 11111111 11111111 11111110 (2(32)-2)
......
1:00000000 00000000 00000000 00000001
0:00000000 00000000 00000000 00000000
虚拟内存这么大,底层对应的物理内存空间也这么大吗?
当然不可能,如果是这样的话运行40个进程,所占物理内存空间就 == 4G*40(160G)这么大,
这是不可能的,就我们个人电脑来说,4G、8G、16G也就很大了,160G是什么概念。
所以每个进程在运行时,虚拟内存底层实际所需的物理内存空间并不大。
而且虚拟内存的虚拟地址也不是全用上了,这个范围太大了,OS做了限制,实际上虚拟地址也只使用
了其中的一部分而已。
不过这里还是简单的回答一下,在众多原因中,有一个很重要的原因是,通过虚拟内存机制,可以让
每个进程拥有完全独立的进程空间
4)每个进程空间的虚拟地址完全相同,会不会相互干扰
(a)什么是相互干扰
所谓干扰就是,既然所有进程的虚拟地址都是相同的,会不会出现使用“虚拟地址”访问自己的进
程空间(虚拟内存空间)时,不小心访问到别人的进程空间中,把别人进程空间的代码和数据给修
改了。
相互干扰有危害吗?
进程间相互干扰是一件很要命的事情,如果其中某个进程是黑客所写的木马或者病毒的话,它就可
以通过这种进程间相互干扰的方式,把别人进程空间中的代码和数据给修改掉,以实现不可告人的
目的。
(c)每个进程空间拥有完全相同的虚拟地址时,到底会不会相互干扰呢?
当然不会,如果会的话,虚拟内存就没有意义了
虚拟内存的一个重要作用就是,可以让每个进程拥有完全独立的进程空间,如此一来
你操作你的代码和数据,我操作我的代码和数据,进程间绝对不会相互干扰。
(d)虚拟内存是如何做到,让进程间不会相互干扰的
比如1楼的房间编号为001~300,二楼的房间编号也是001~300,编号虽然相
同,但是对应的完全是并不同的房间。
同样的道理,虽然所有进程空间(虚拟内存空间)的虚拟地址(编号)是一样的,但是各自在物理
内存上,实际所对应的物理内存空间完全不同。
为什么每个进程空间(虚拟内存)各自对应的是完全独立的物理内存空间?
虚拟内存通过特殊的实现机制,它可以严格保证每个虚拟内存,各自对应的是完全独立的物理内
存空间。
每个进程使用各自的虚拟地址访问时,最终操作的是自己物理内存空间中的代码和数据,绝不会误
操作。
说白了就是虚拟内存机制可以保证,每个程序完全运行在各自独立的物理内存空间,而且还能保证
它们绝对不会误访问得到对方的物理内存空间
5)让每个进程拥有独立进程空间的好处
(a)好处非常多,最关键的好处就是防止别人攻击
有了独立的进程空间后,每个进程的都只在OS提供的独立的进程空间(虚拟内存)里面运行,这样既
有效的防止了你去害别人,也防止了别人害你。
病毒、木马基于OS运行起来后,也是一个独立的进程,由于它的进程空间也是完全独立,所以进程空
间之间没有任何的交集,因此木马和病毒根本无法修改其它进程空间中的代码和数据,所以有效的预防了
木马和病毒的攻击。
(b)难道病毒、木马真的就没有攻击的办法了吗
如果病毒、木马被做成应用程序,是以应用程序的身份来运行的,那么它只能运行在OS所提供的独立
的进程空间里面,这种情况下,它还真是没办法去攻击别人,所以现在根本就不存在应用级的木马和
病毒(应用程序形式的木马和病毒)。
现在的木马和病毒如果真想搞事的话,只能是系统级的木马和病毒,就是木马和病毒能够直接攻击OS,
以实现攻击的目的。
为什么只有攻击OS才能成功实现攻击呢?
因为独立的进程空间是由OS的虚拟内存机制提供的,如果木马和病毒以应用程序运行,那么它就只能
被限制在独立的进程空间中,如果木马和病毒想要攻击,只能釜底抽薪,打入敌人(OS)内部才能
实现,木马和病毒一旦攻击OS成功,基本就是想干啥就能干啥了。
就像古代攻城一样,外面固若金汤很难突破,此时如果从内部去瓦解,很快就能攻破
当然现在OS的安全级别也越来越高,也不是想要入侵就能入侵的
6)独立进程空间的缺点
世界上就不存在只有优点而没有缺点的事物,往往有些时候优点的反面就是缺点,每个进程拥有独立的
进程空间,显然是一个可以防止别人攻击的优点,但是这个优点反过来也带来了一个缺点,那就是由于进
程空间独立性,导致进程间的数据共享很困难。
但是进程之间确实有共享数据的需求,需要共享数据时怎么办呢?
此时OS为了弥补进程间共享数据困难,OS提供了各种的“进程间通信”,以实现数据的共享。
5. 进程间通信
(1)进程间通信的原理
尽管进程空间是各自独立的,相互之间没有任何可以共享的空间,但是至少还有一样东西是所有进程所共
享的,那就是OS,因为甭管运行有多少个进程,但是它们共用OS只有一个。
既然大家共用的是同一个OS,那么显然,所有的进程可以通过大家都共享第三方OS来实现数据的转发。
因此进程间通信的原理就是,OS作为所有进程共享的第三方,会提供相关的机制,以实现进程间数据的转发,
达到数据共享的目的。
(2)广义上的进程间通信
其实广义上来说,任何一种能够实现进程间数据交换的方式,都可以被称为进程间通信,比如
A进程——————文件———————B进程
A进程—————数据库——————B进程
不过一般来说,这种广义的进程间通信,并不被算作真正的“进程间通信”。
只有OS所提供的专门的通信机制,才能算作是真正的“进程间通信”,我们本章所讲的就是狭义上的真正的
“进程间通信”。
(2)Linux提供的“进程通信”方式有哪些
Linux的父亲是Unix,所以Linux的进程间通信,其实都是继承于Unix。
不管继承自谁,Linux所提供的进程间通信机制到底有哪些呢?
1)信号
上一章讲的信号其实也是进程间通信的一种,只不过信号是非精确通信,而本章讲的IPC是精确通信。
所谓精确通信,就是能告诉你详细信息,而信号这种非精确通信,只能通知某件事情发生了,但是无法
告诉详细信息。
2)这里的进程间通信
(a)管道
· 无名管道
· 有名管道
OS在进程之间建立一个“管道”,通过这个管道来实现进程间数据的交换。
(b)system V IPC
· 消息队列:通过消息队列来通信
· 共享内存:通过共享内存来通信
· 信号量:借助通信来实现资源的保护(一种加锁机制)
3)域套接字

浙公网安备 33010602011771号