每天积累一点点,终有一天会水落石出,不明白的地方越来越多,对于分布式计算从底层开始走起,会理解的更深刻。
进程间的通信是什么?和分布式又怎么扯上了关系? 怎么定义? 缠绕心中,不得其所
1、进行间通信的基本原理
在网络和分布式程序设计中,进程间通信(IPC: Inter-Process Communication)是非常重要的开发方法。进行间通信大致可以分为两类:一类是应用在同一节点上的进程间通信方法,主要有管道、FIFO、信号、消息对列和共享内存等;另一类是应用在不同节点上的进程间通信方法,基于套接字(Sockets)的通信是一种典型方法。
可以把Java进行理解为JVM进程,其进程间通信依靠系统调用来实现。Java要实现进程间通信,可以使用RMI或者CORBA。事实上,Java的CORAB也是通过RMI来实现的,而RMI归根结底也是利用Socket来实现的。所以说Java进程间通信的最基本手段是Socket也不为过。
例程Inprocess 是用共享内存的方式实现进程间通信。
进程间通信Inprocess简易图
import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class Producer extends Thread { private String mFileName; private FileChannel mFileChannel; private MappedByteBuffer mMappedByteBuffer; public Producer(String fn){ try{ mFileName=fn; //获得一个可读写的随机存取文件对象 RandomAccessFile RAFile=new RandomAccessFile(mFileName,"rw"); //获得相应的文件通道 mFileChannel =RAFile.getChannel(); //设定文件大小,以便映像到共享内存 int size=10000; //获得共享内存缓冲区,该共享内存可读 mMappedByteBuffer =mFileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size).load(); }catch(IOException ex){ System.out.println(ex); } } public void run(){ int i=0; while(true){ try{ FileLock lock=null; lock=mFileChannel.tryLock(); if(lock==null){ System.err.println("Producer:lock failed"); continue; } mMappedByteBuffer .putInt(0,++i); mMappedByteBuffer.putInt(4,++i); mMappedByteBuffer.putInt(8,++i); System.out.println("Producer:"+(i-3)+":"+(i-2)+":"+(i-1)); Thread.sleep(200); lock.release(); Thread.sleep(500); }catch(IOException ex){ System.out.println(ex); }catch(InterruptedException ex){ System.out.println(ex); } } } public static void main(String[] args) { Producer producer=new Producer("sharedMemory"); producer.run(); } }
该程序定义了一个用java线程机制实现的简单缓冲区。该缓冲区获得一个可读写的随机存取文件对象。Producer类利用Thread类的派生创建一个新线程,并直接创建该线程类的一个实例。线程启动后,线程向缓冲区中写入数据的生产者线程,该线程连续不断地每隔一段时间就往缓冲区中放入一个新数据。
import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class Consumer extends Thread{ private String mFileName; private FileChannel mFileChannel; private MappedByteBuffer mMappedByteBuffer; public Consumer(String fn){ try{ mFileName=fn; //获得一个可读写的随机存取文件对象 RandomAccessFile RAFile=new RandomAccessFile(mFileName,"r"); //获得相应的文件通道 mFileChannel =RAFile.getChannel(); //设定文件大小,以便映像到共享内存 int size=10000; //获得共享内存缓冲区,该共享内存可读 mMappedByteBuffer=mFileChannel.map(FileChannel.MapMode.READ_ONLY,0,size).load(); }catch(IOException ex){ System.out.println(ex); } } public void run(){ while(true){ try{ Thread.sleep(300); FileLock lock=null; lock=mFileChannel.tryLock(0,10,true); if(lock==null){ System.err.println("Consumer:lock failed"); continue; } Thread.sleep(200); System.out.println("Consumer: "+mMappedByteBuffer.getInt(0)+":"+mMappedByteBuffer.getInt(4)+":"+mMappedByteBuffer.getInt(8)); lock.release(); }catch(IOException ex){ System.out.println(ex); }catch(InterruptedException ex){ System.out.println(ex); } } } public static void main(String[] args) { Consumer consumer=new Consumer("sharedMemory"); consumer.start(); } }
该程序也用java线程机制实现了一个简单的缓冲区。该缓冲区获得一个可读写的随机存取文件对象,获得相应的文件通道,取得文件的实际大小,以映像到共享内存,获得共享内存缓冲区。Consumer类利用Thread类的派生类创建一个新线程,并直接创建该线程类的一个实例。线程启动后,线程从缓冲区中读出数据的消费者线程,该线程不断地从缓冲区中取出数据并显示在屏幕上。
2、 接口与接口定义语言
接口定义语言也称为接口描述语言(IDL),是描述软件组件接口的语言规范。IDL用中立语言的方式进行描述,能使软件组件(用不同的语言编写)间实现相互通信。IDL提供了将对象的接口与其实现分离的能力,将事务与其具体实现分离的概念。
3、数据表示与编码
进行间通信是分布式系统中首要解决的基本问题。在面向对象的分布式系统中,进程间通信通常表现为远程对象间的消息传递。在通信双方的进程维护着消息队列,发送进程将消息先放到发送方缓冲区,并通过通信信道到达目的主机的接收缓冲区,接收进程从缓冲区取出数据。要在基于二进制流的网络上传递抽象的数据类型或对象,必须以通信双发可以理解的格式对数据进行编码。
不同抽象层数据表示标准
外部数据表示(XDR:EXternal Data Representation) 是SunSoft提供的一种与体系结构无关的数据表示方法,解决了数据字节排序的差异、数据字节大小、数据表示和数据对准的方式。使用XDR的应用程序,可以在异构硬件系统上交换数据。
抽象语法标记 ASN.1(Abstrat Syntax Notation One) 是在较高抽象层上对数据进行表示、编码、传输和解码的数据格式。ASN.1及其编码规则进行了结构化数据的传输,以一种独立于计算机架构和语言的方式来描述数据结构。
在更高的抽象层次,并且也是应用较为广泛的是可扩展标记语言 (XML:Extensible Markup Language)。 XML继承了通用标记语言标准(SGML:Standard for General Markup Language)具有的可扩展性(用户能够根据需要,自行定义新的标识及属性名)、结构性(XML 的文件结构嵌套可以复杂到任意程度,能表示面向对象的等级层次)及可校验性(XML文件可以包括一个语法描述,使应用程序可以对此文件进行结构确认)。因此,XML使得分布式系统之间的数据交换更为容易,允许数据在应用系统间共享。
4、事件同步机制
由于进程间通信的相关进程是独立执行的,各进程间不知道对方进程的执行情况,所以,进程间通信设施常采用事件同步机制。最简单的事件同步方法是阻塞机制,即挂起某一进程的执行,直到该进程发起的某个操作执行结束。
根据进程间同步方式的不同,可将进程间通信方式分为3种。
1)同步通信:放送方发出消息后就等待,直到接收方返回确认信息才继续执行。
2)异步通信:发送方发出消息后依然继续执行,再利用空闲时间对接收方进行轮询,以检查请求是否已处理完毕。
3)单向通信:发送方发出消息后依然继续执行,不再询问请求是否处理完成。
参考:
《分布式计算实验教程》