首页 > 代码库 > 分布式计算(二)进程间通信

分布式计算(二)进程间通信

     每天积累一点点,终有一天会水落石出,不明白的地方越来越多,对于分布式计算从底层开始走起,会理解的更深刻。

 进程间的通信是什么?和分布式又怎么扯上了关系? 怎么定义? 缠绕心中,不得其所


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)单向通信:发送方发出消息后依然继续执行,不再询问请求是否处理完成。

      

 

参考:

 《分布式计算实验教程》





分布式计算(二)进程间通信