新手学C++多线程编程(7)接口类与进程间通信

来源:互联网 发布:盛夏光年知乎 编辑:程序博客网 时间:2024/06/06 00:03

C++多线程编程(7)接口类与进程间通信

 
转载

C++多线程编程(7)

 

接口类与进程间通信

 

1.接口类:用于修改或改进另一个类或一系列类的接口。同时用来给非面向对象代码和数据提供面向对象接口或一个接口类来处理非面向对象过程及其数据。通过将过程化代码和数据封装在一个接口类中,让它面向对象化。接口类的一个重要用途:为数据和需要操作于该数据的函数提供独立域接口。

 

2.适配器(adaptor):修改其他类接口的类,它为其他现有面向对象类提供封装器。目标非添加新功能,而是提供一个新的语义正确的类的接口。
容器适配器:为标准模板库STL中的list、vector和deque容器提供了一个新的公共接口。
适配的2个技术途径:(1)私有继承:一个适配器类可能只选择修改被转换类的部分成员函数,对于所有成员函数都不被修改的情况,被修改类的私有继承提供了一定程度的安全性 (2)使用类封存(containment)或合成(composition):class Stack{protected:Container c;..},其中在c中被赋予了新接口的成员函数才能被访问。

【注意】使用适配技术,接口类可以使用类修改后的实现来预定所需要的访问。并不是所有接口类都重命名现在的实现。若只是重命名适配类的成员函数,使用内联技术是最有利的,最大限度降低重命名的开销。

 

3.蓝图接口类:提供一个接口,但没有任何实现,不包含数据,为将来的类提供基础。所有成员函数定义为纯虚函数,所有基类也为接口类。指定程序员在使用该类时,必须实现哪些成员函数。

 

4.接口类封装过程代码和数据的附带作用:减少调用新成员函数时的参数。

 

5.C++没有多线程并发处理或进程间通信的关键字,必须用类、类库和应用框架的形式构建这种支持。将并行处理和多线程处理推到库或类库的高度,C++获得最灵活的处理方式。唯一并发模型:重用操作系统代码,设计IPC类、线程控制类和进程控制类,然后生成一个接口类,使用这些接口类再构建任务和线程类,使用任务和线程类可以构建线程和任务库。最后,使用线程和任务库构建多线程应用框架。

 

6.面向对象接口到管道:
任何面向对象处理方式至少有5个组件:数据缓冲器、数据缓冲器插入操作、数据缓冲器提取操作、数据缓冲器创建操作、数据缓冲器析构操作。抽象管道除了这5个组件外,还包括输入端口和输出端口,这样就构成了抽象管道的最小需求。使用两种技术来创建面向对象管道:(1)使用面向对象工具,如iostream层次  (2)复合和fstream对象来创建pstream对象(管道类)。

 

7.iostream类层次3种主要组件:a.缓冲器组件(传送中的字节的保存区)、b.翻译组件(匿名字节序列翻译成适当数据类型和数据结构,同时将数据结构和数据类型翻译成匿名字节序列;提供字节流信号量,其中所有I/O都被看做字节流)、c.状态组件(显示可用于缓冲器组件中数据字节的格式类型;显示流是否追加、创建、排他性读或排他性写模式中已经打开;数字是否被解释成十六进制、八进制或二进制;用于判断对于缓冲器组件的I/O操作错误状态)。3个组件可以一起使用形成一个完全面向对象流,或单独作为其他任务中的支持对象。

 

8.使用提取器和插入器进行自动格式翻译是使用fstream类家族与管道通信的一个主要优点。使用iostream进行进程间通信可以让进程通过管道发送对象。

 

9.使用STL ostream_iterator和istream_iterator的匿名管道:
istream_iterator: a==b(等价)、a!=b(非等价)、*a(反引用)、++r(前增量)、r++(后增量)
ostream_iterator:++r(前增量)、r++(后增量)

 

10.ostream_iterator X(cout," "); //X就是一个ostream_iterator类型的对象
 增量操作:X++; //将X移到输出流的下一个为止
 *X=Y; //导致Y在标准输出显示
 ostream_iterator对象的赋值运算符最终导致如下语句被执行:*stream<<value;
 istream_iterator对象的赋值运算符最终导致如下语句被执行:*stream>>value;

  template<class T>
  class ostream_iterator:public output_iterator
  {protected:
        ostream* stream;
        char* string;
   public:
        ostream_iterator(ostream& s):stream(&s),string(0){}
        ostream_iterator(ostream& s,char* c):stream(&s),string(c){}
        ostream_iterator& operator=(const T& value){
           *stream<<value;
           if (string)*stream<<string;
           return *this;
      }
       ostream_iterator& operator*(){return *this;}
       ostream_iterator& operator++(){return *this;}
       ostream_iterator& operator++(int){return *this;}
  };

  如果istream_iterator和ostream_iterator对象都与iostream对象连接,iostream对象反过来又与管道文件描述符连接,每次推进istream_iterator时就读取管道,每次推进ostream_iterator时就写入管道。


【程序演示】如何在进程间通信中使用迭代器类:

C++多线程编程(7)接口类与进程间通信
C++多线程编程(7)接口类与进程间通信

转换算法transform()的实现:
template<class InputIterator,class OutputIterator,class UnaryOperation> OutputIterator
transform(InputIterator first,InputIterator last,OutputIterator result,UnaryOperation op)
{ while(first!=last)
    *result++=op(*first++);
  return result;
}
 

可用输入输出迭代器的STL算法:

C++多线程编程(7)接口类与进程间通信

11.使用接口类实现面向对象命名管道(named pipe):
   使用匿名管道技术的2个弊端:(1)文件描述符没有封装,可被程序中任何函数操纵。(2)进程间通信只限制于关联进程(即父子进程)。
   命名管道为管道添加最重要一个特征:允许不关联的进程通过文件名的等价体来访问一个管道。
   服务器进程(server process)/客户机进程(client process),服务器进程负责建立命名管道的属性,而客户机进程则通过名字打开管道。服务器进程可以有多个使用管道的客户进程。
  命名管道可以命名包含服务器或网络上另一台机器的域名,如\\ServerName\PIPE\mypipe
 
12.基本命名管道的抽象具备以下组件(WIN32或OS/2中):
 管道名字、访问权限(是否允许访问)、打开模式(输入或输出或既输入又输出、管道读写是否阻塞或非阻塞模式)、管道模式(消息流或字节流模式)、输入端口、输出端口、输入端口大小、输出端口大小、数据缓冲器、数据缓冲器插入操作、数据缓冲器提取操作、数据缓冲器创建操作、数据缓冲器析构操作。

如果在UNIX环境中不要求具备所有这些组件,但需要使用套接字(socket)进行企业内联网和国际互联网间进行无关进程间的通信。

 

13.npstream类作为给命名管道提供系统API面向对象接口的封装器。通过与fstream对象的包容关系,npstream类是命名管道功能与iostream提供的I/O面向对象模型的合成。意味着我们可以使用npstream类来创建用于关联进程间、非关联进程间以及网络间通信的对象。

 

14.npstream接口类:
 template <class T>
 class npstream
 { private:
     char PipeName[20];  //管道名字
     unsigned long PipeHandle; //管道句柄
     long int PipeMode; //管道模式
     long int OpenMode; //打开模式
     long int InputBufSize; //输入字节流大小

     long int OutputBufSize;//输出字节流大小
     long int TimeOut; //超时时间
     unsigned long Result;//管道对象
     fstream NamedPipe; //指向管道句柄的流对象
   public:
     npstream(char *PName,long PMode,long OMode,log TOut=1000);//构造函数1
     npstream(char *PName);//构造函数2
     ostream &operator<<(T &X); //插入器
     istream &operator>>(T &X); //提取器

     void operator<<(vector<T>& X);//扩展使用ostream_iterator迭代器

     void operator>>(vector<T>& X);//扩展使用istream_iterator迭代器
     long int pipeMode(void);
     long int openMode(void);
     long int outBufSize(void);
     long int timeOut(void);
     unsigned long result(void);
 };

 【程序演示1】一个服务器进程,创建一个命名管道,从客户进程读取一个字符串,然后显示该字符串:

C++多线程编程(7)接口类与进程间通信

 【程序演示2】在命名管道中写入一个字符串的客户进程:

C++多线程编程(7)接口类与进程间通信
 为了让客户与服务器使用相同的管道,客户必须在构造函数中指定与服务器管道名字一致的正确的名字。

 

15.npstream状态:2种关联状态(管道状态 和 fstream对象状态)
(1)fstream对象状态封装了三种状态:
a.打开模型状态(读、写或既读又写、流是否按文本或二进制模式打开)
b.缓冲器状态(包含在filebuf对象,NamedPipe.good()、NamedPipe.bad()、NamedPipe.fail()、NamedPipe.eof() 协助决定附加管道是否仍处于工作条件)
c.格式状态(显示数值精确度十六进制十进制或八进制格式的信息、是否左对齐右对齐的信息、数值是定点浮点科学记数法信息:NamedPipe.setf(ios::fixed|ios::showpoint); NamedPipe.precision(4);NamedPipe<<setiosflags(ios::hex);)
(2)管道状态:管道模式、打开模式、管道名字、实例计数、输入缓冲器大小、输出缓冲器大小、时间耗尽
long int pipeMode(void);
long int openMode(void);
long int outBufsize(void);
long int inBufsize(void);
long int timeOut(void);
 

16.命名管道与STL istream_iterator和ostream_iterator:

命名管道可以通过iostream对象进行连接,扩展npstream类定义另一个运算符<<:

void operator<<(vector<T>& X);

template<class T>

void npstream<T>::operator<<(vector<T> &X)

{ ostream_iterator<T> Out(NamePipe," ");

  copy(X.begin(),X.end(),Out); //沿管道发送对象

原创粉丝点击