




已阅读5页,还剩24页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
摘要跨平台是软件开发中一个重要的概念,即不依赖于操作系统,也不信赖硬件环境。一个操作系统下开发的应用,放到另一个操作系统下依然可以运行。相对而言如果某种计算机语言不用修改代码即可做到高度跨平台,那么此语言就越抽象,硬件控制力就越低,只适合开发高度抽象的模型系统。文中提到的当下比较流行的开源库如Boost,Qt, ZThreads,Ptypes,这些开发库各有各的侧重点,在性能和框架设计上各有不同,本文会依次简要分析这些开发库的设计原则,概括总结跨平台有两种实现方式,利用分支技术,或者利用动态平台识别,例如Java是一种提供运行环境的跨平台解决方案,而C只是一种标准且严格的跨平台语言,本文就是主要探讨C的跨平台库实现。本文会简要分析几种跨平台的技术实现和区别,并通过对实现方法的总结,而借用一种叫做核心和路由的技术来实现跨平台库的构架,并给出相应实现,最后配上相应的演示功能程序。关键词:跨平台、开源库、Boost、线程库AbstractCross-platform software development is an important concept, that is not dependent on the operating system, do not trust the hardware environment. An operating system developed under the application can still run into another operating system. In contrast If a computer language without modifying the code to achieve a high degree of cross-platform, then the more abstract language, lower hardware control, only suitable for the development of highly abstract model system.Current popular open source libraries such as Boost, of Qt, ZThreads, Ptypes, each of these development libraries each focus on performance and frame design different, this article will be followed by a brief analysis of the design principles of these development libraries, text summary cross-platform implemented in two ways, a branch of technology, or the use of a dynamic platform to identify, for example, Java is a cross-platform operating environment solutions, and C is a standard and rigorous cross-platform language, this paper focuses on C cross-platform library.This article is a brief analysis of several cross-platform technology and distinction, and summary of the implementation, and to borrow a technique called core and routing technology to achieve cross-platform library architecture, and gives the corresponding implementation, and finally coupled with the corresponding demo program.Key words: cross-platform, open source library, Boost thread library目录摘要1Abstract2第一章 引言41.1研究背景41.2主要研究内容51.3论文结构5第2章 跨平台软件开发环境62.1跨平台开发的历史62.2预处理器使用62.2.1例子 1: Boost 线程库72.2.2例子 2: ZThreads 线程库82.2.3预处理技术的比较92.2 独立的开发分支102.3 设计模式112.3.1 桥接模式122.3.2 抽象工厂模式13第3章 跨平台库的设计153.1介绍153.2核心和路由概述153.3应用范例17第4章 跨平台线程库的设计和实现204.1 线程跨平台的基础204.2总体框架设计214.3 线程库结构化实现23第5章 总结与展望285.1 总结285.1 展望28致 谢29参考文献30第一章 引言1.1研究背景1991年Linux出现。短短10多年,Linux已经迅速发展成为一个至关重要的操作系统。目前Linux技术1已成为国内外信息产业界研究开发的热点。基于Linux的软件产品已经基本覆盖了计算机软件的各种门类。但与Windows相比。用户可供选择的优秀系统软件数量还不太多。如何利用已有的Windows下的软件资源,迅速的开发出Linux下优秀的应用软件,缩短软件开发周期,已经成为一个热点。将Windows软件向Linux软件移植将是一个很好的选择,因此如果可以拥有更多的跨平台的库去丰富代码,那么移植也会变得非常轻松。大部分电脑语言从绝对意义而言,都是跨平台的:因为都是以高级的、人类可读的方式来对CPU发号指令,这样也就没必要依赖于任何作业系统。但如果要用系统的部件工具箱,来新建用户图形界面(GUI),就可能会用到开发员特定系统中的API函数或库类。虽然C+是跨平台的,但Windows下用到Win32 API的C+程序,一般就不能在Unix机器上编译。不同编译器对语言规范的解释也有所差异。这样的话,在针对不同系统进行构建之前,程序就得加以考虑。一些如Java这样的语言,从一开始就意识到要在各个平台下运行,所以跨平台在其平台的本地语言环境中已经实现。例如,Java可以跨平台使用,正是由于Swing库在许多平台下的实现。类似的,能进行跨平台的文件存取,是因为有各自平台下文件存取的库。以此类推,各种跨平台问题,都需要各自的本地库来解决。wxWidgets框架就是这样的一个跨平台库,根据不同的跨平台问题,提供了许多不同的解决方案;类似的库有许多,可以根据不同语言的跨平台开发,而采用相应的库。那些解释型语言,或者需要虚拟机的语言,也更加符合跨平台的要求,因为用户也要自己进行编译。Sun公司的Java虚拟机Hotspot,只针对几种而不是全部平台,提供编译好的二进位文件。例如,Sun对于GNU/Linux,只支持i386平台,但如果谁在PowerPC或者SPARC电脑上运行Linux,就只好自己编译本地的机器码(machinecode),或者使用第三方软件,才能运行Java程序。许多API(应用程序介面)依赖于平台。OpenGL可以看作是跨平台的,因为其不依赖于任何特定的作业系统、CPU构架或者某个牌子的图形设备。特定平台的API可以在其他系统上作为兼容层而新建,例如WINE的库,Windows程序就可以在UNIX系统上运行。另外许多程序语言还有跨平台的扩展以及中间件,这样程序设计师对于同样的原始码,只要进行一点小修改,就可以在不同平台下编译/运行,例如Qt和wxWidgets。1.2主要研究内容通过学习和研究多种开源库的跨平台技术,并通过对实现方法的总结,而通过运用被称作核心和路由的技术,来实现一种跨平台的线程库,并给出相应实现,最后配上相应的演示功能程序。1.3论文结构本文划分为六章,文章的安排结构如下:第一章简单介绍了跨平台开发库的历史背景,并指出了其在软件开发的重要意义。第二章介绍跨平台开发的开发环境及几种流行的开发库。第三章跨平台开发库的框架设计。第四章跨平台线程库的设计与实现。第五章总结了关于跨平台库的几点重要特性,并指明了下一步改进计划。第2章 跨平台软件开发环境本章讨论了常见的跨平台软件开发方法。开始小节讨论的历史和跨平台的开发方法给出了一个简单的发展,第2小节讨论了跨平台软件开发的第一种方法:在编译时大量使用预处理器剥离源代码,而在第3小节讨论了跨平台软件开发的第二种方法:使用不同的开发分支为每个目标平台。第4小节提出了分类比较这篇论文的软件包,而最后小节简要介绍对于跨平台软件开发中所需要的设计模式及其意义。2.1跨平台开发的历史也许最好的方式理解什么是跨平台开发技术以及研究它们起源。对于很大一部分早期的UNIX发展的,从大约1969年到1976年不等,有没有这样的东西作为跨平台的软件。一个非常具体的硬件/软件平台编写的软件。如果平台绝种了,整个包会被移植到老平台的继任者。一旦多种硬件和软件平台的进一步普及,UNIX内核需要一种方法来编译和运行在许多不同的平台上。随着程序和Makefile文件2在1979年,预处理器被广泛应用在寻求在多个平台上编译的应用程序。原来的makefile不仅智能编译源文件,也可以将命令行参数传递给编译器。传递的参数大部分预处理器已经被定义。随着时间的推移,更多的软件包针对多个平台,最终,独立的开发分支,每个平台的想法来的。源文件包含对每个平台的代码,而是将分成分支机构发展。每个分支只包含为特定的平台所需的源代码,从而减少了由预处理器条件检查。2.2预处理器使用在第一个跨平台的软件开发方法3,源文件遍布预处理语句,这使得代码难以阅读,容易出错,很难在所有平台上进行测试,并难以维持。软件包依赖于这种方法的例子是Boost,ZThreads。此外,可能读者会注意的POSIX线程包采用提到的方法,但本篇论文认为,“单独的分支”类别更适合它。一个有趣的现象是,尽管所有这些包预处理大量使用,但他们使用它的方式不同,下面介绍在各自的小节。然而,即使采用四种不同的方法,使用预处理器,但并没有很好的可读性,代码的安全性也未达成。每个包所采用的方法是最有可能使用,因为每个包已经习惯了各自的作者说的方法。这个论文并没有办法旨在宣布优于任何其他这些软件包之一,只是在于观察每个方法的安全性和可读性。2.2.1例子 1: Boost 线程库Boost是个c+程序库开发的社区和平台,这个组织开发出的程序库被统称为Boost程序库4,由于其很多成员在c+的标准化组织具有很高地位,因此Boost库被称为“准标准”程序库,在c+爱好者中影响非常广泛。其许多程序库被广为使用。相对于操作系统提供的API函数来创建多线程程序而言,Boost线程库是使用到了许多的c+特性,例如构造函数和析构函数、函数对象、模板等等,都可以在其中使用,使其接口更加灵活。现在的版本已经可以在POSIX、Win32和Macintosh Carbon平台下工作。而且相对于c+其它方式的编程,其学习成本更低,而且配合使用Bost库中的其它类库,比如智能指库和Bind库,能大大减少编程量,更易编出高质量的c+多线程程序。Boost的实现可能是最难读懂预处理的方法。Boost使用预处理器部分,出特定于平台的功能实现而且会去识别各种版本的编译器。Boost还采用了预处理有条件地确定哪些变量要存储在类中。这种做法是非常危险的,因为使用者可能预期一定的预处理条件是真实的时候,而实际不是这样,使得类的定义理解错误,并可能导致不明情况的运行错误,下面简要分析一下Boost的thread跨平台处理。class BOOST_THREAD_DECL thread public: typedef thread_attributes attributes;BOOST_THREAD_MOVABLE_ONLY(thread) private:struct dummy;void release_handle();detail:thread_data_ptr thread_info; private: bool start_thread_noexcept(); bool start_thread_noexcept(const attributes& attr);. source code is here;图2.1 摘自 Boost 源代码 (Thread.hpp)定义thread classboost/thread/detail/platform.hpp 识别平台boostlibsthreadsrcwin32thread.cppboostlibsthreadsrcpthreadthread.cpppthread thread class 实现win32 thread class 实现图2.2 Boost平台识别正如上面的图解,Boost在实现线程库时通过延迟类的实现,来实现线程库,platform.hpp文件包含了大量的关于系统和编译器的宏,可以正确的识别当前的环境,然后再进行线程类的实现,对于调用者来讲,只需关注thread类的定义,不管在任何系统下,使用的规则不变,这样跨平台的效果就达到了。2.2.2例子 2: ZThreads 线程库ZThreads是一个用C+编写的跨平台的线程API。使用预处理语句内包含正常条件定义和执行的语句。在一些地方,它并没有直接用预处理语句区的剥离可执行代码,ZThreads反而会包含特定于平台的实现源代码。这有助于代码的效率,但仍然使得跟踪源文件的一个问题,因为它可以很难确定哪些文件是通不过的,而这种方式也正是无法达到两全其美的状态,大多数的ZThreads代码是在写入这种方式。下面显示了ZThreads有条件地定义实现文件包括的一个例子。#if defined(ZT_POSIX)# include posix/ThreadOps.h# define ZT_THREADOPS_IMPLEMENTATION posix/ThreadOps.cxx#elif defined(ZT_WIN32) | defined(ZT_WIN9X). more source code here# include win32/ThreadOps.h# define ZT_THREADOPS_IMPLEMENTATION win32/ThreadOps.cxx#elif defined(ZT_MACOS)# include macos/ThreadOps.h#define ZT_THREADOPS_IMPLEMENTATION macos/ThreadOps.cxx#endif图2.3 摘自 ZThreads 源代码 (ThreadOpts.h)2.2.3预处理技术的比较当然还有一些其他的比较优秀的库,也使用了预处理技术去实现跨平台,在此就没有详细介绍,在这里就概括性的给出其中的比较性。不过从其中也可以看出各自的优劣性。就像MsgConnect可能本身是给Windows设计的库,但是为了也希望Linux可以调用,又不想改写接口,于是就直接将Linux的接口封装为Windows的标准接口,这样就是进行平台仿真。利用预处理器技术的跨平台比较Boost ThreadsHawkNLMsgConnectZThreads条件编译函数X可变化的结构成员XXXX条件编译源文件XXX进行平台仿真X图2.4 跨平台技术比较2.2 独立的开发分支跨平台软件开发的第二种方法归类为具有源代码分割成单独的开发分支。有点相似的是,Java以语言角度算是不错的语言,语法干净简洁,OO支持也算完整,Framework设计的也不错,写出来的程序语法也蛮漂亮的,还Open Source,且支持应用很广,从GUI、Component、Web、Embedded都有支持,但Java技术最大的致命伤就是执行速度缓慢,透过Virtual Machine技术使得Java得以实现跨平台,什么是Virtual Machine呢?简单的说,就是在给个OS上在装一个JavaOS跑Java程序,这种方式就像你写了一个Windows程序,然后也宣称是跨平台,只要User在Linux或Mac装上VMWare,然后在VMWare下灌Windows XP,这样也能在Linux、Mac下执行你的Windows程序,但经验告诉我们,用VMWare跑其它OS,速度大约只剩下6成左右而已,Java程序速度慢的原因就在这里,这是Virtual Machine的宿命。而单独的开发分支不是虚拟机,而是实实在在的底层接口的封装,现在这一类的包是相当大的,继续保持积极发展的状态。使用单独的开发分支项OpenSG,QT,GTK和POSIX线程。所有这些项目仍处于积极开发和细化中,他们都支持多种平台。例如,OpenSG支持4作业系统(Windows, Vanilla Linux, Irix, 和 Irix64),一共有5个编译器(英特尔的编译器,微软的优化编译器为ISO C + +,GCC3.2及以上,SGI CC,和SGI64位CC)。 一些不可忽略的副作用却会因为包被分成多个开发分支而产生。首先,最小化的代码共享。有时访问平台特定的对象和功能,从而使其更难编写独立于平台的代码。但是最严重的副作用在于发展情况下一个小的设计变更或增强时,而这种改变,需要不同程度的努力将其移植到许多不同的平台上。在有些封装中中,一个应用程序员可能会因为某项特殊发功能需要,而打破的write-once/compile-anywhere的的模型。 QT允许在某些情况下,从基类的到所有Qt的窗口小工具可以进行扩展以适应特定平台需要,QWidget的代码摘录,如图所示。自QWidget的以来类给出了到特定于平台的功能的访问,而可能一些程序员可能会喜欢上这种方式,以实现特定于平台的功能。 #ifndef QWIDGET_H#define QWIDGET_Hclass Q_EXPORT QWidget : public QObject, public QPaintDevice. more source is herepublic:QWidget( QWidget *parent=0, const char *name=0, WFlags f=0 );QWidget();WIdwinId() const;voidsetName( const char *name );#if defined(Q_WS_MAC) virtual bool macEvent( MSG * );#endif#if defined(Q_WS_WIN) virtual bool winEvent( MSG * );#endif#if defined(Q_WS_X11) virtual bool x11Event( XEvent * );#endif#if defined(Q_WS_QWS) virtual bool qwsEvent( QWSEvent * ); virtual unsigned char *scanLine( int ) const; virtual int bytesPerLine() const;#endif. more source is here;图2.5 Qt平台拓展代码Qt拥有一个单一的Library,让你开发各种不同平台的程序,目前支持Windows、Linux、Mac、UNIX、Embedded Linux,讲白话点,就是它提供了一个Library让你开发GUI程序,写好之后,只要在各平台重新Compile后,就可以在各平台执行,而且使用完整的ANSI C+语言,且不限Compiler,只要是C+的Compiler都可以,重要的是,该Library相当漂亮,写出来的程序很像C+ Builder或.NET Framework的那样精简,不会向MFC那样复杂。然而库从发展的角度来看,管理多个分支机构,可以是一个艰巨的任务。一个小变化(简单的加法或减法的一个成员函数)的分支可能煽动整个代码,而重新写另一个分支。这迫使API和库设计师有一个复杂的知识,必须面对的问题就是如何实现各分支,使一个开发分支提出变更时,不会突然落在后面所有的其他分支。2.3 设计模式设计模式5是真实世界的编程解决方案的代表。设计模式开始出现在20世纪70年代中后期出版工作,更普遍的东西,只是一个更好的方式来实现想法规划,建设,架构和代表性。设计模式允许程序员可以轻松地分享他们的程序的体系结构,可以分成三大类:创建模式创建型模式抽象了实例化过程。他们帮助一个系统独立于如何创建、组合和表示他的那些对象。一个类创建型模式使用继承改变被实例化的类。而一个对象创建型模式将实例化委托给另一个对象。结构模式结构型模式涉及到如何组合类和对象以获得更大的结构。结构型模式采用继承机制来组合接口或实现。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。行为模式行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象和类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的复杂的控制流。他们将你的注意力从控制流转移到对象间的联系方式上来。本文在实现跨平台线程库是将会依赖于造物的模式和结构模式,提供一个跨平台开发API的更优雅的方式。具体的使用的设计模式是桥接和抽象工厂。所以在此详细介绍一下这两种设计模式。2.3.1 桥接模式定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。类型:行为类模式类图:图 2.6 桥接模式UML图为了达到让抽象部分和实现部分都可以独立变化的目的,在桥接模式中,是把抽象部分和实现部分分离开来的,虽然从程序结构上是分开了,但是在抽象部分实现的时候,还是需要使用具体的实现的,这可怎么办呢?抽象部分如何才能调用到具体实现部分的功能呢?很简单,搭个桥不就可以了,搭个桥,让抽象部分通过这个桥就可以调用到实现部分的功能了,因此需要桥接。桥接模式的优点适当地使用桥接模式可以避免同事类之间的过度耦合,使得各同事类之间可以相对独立地使用。使用桥接模式可以将对象间一对多的关联转变为一对一的关联,使对象间的关系易于理解和维护。使用桥接模式可以将对象的行为和协作进行抽象,能够比较灵活的处理对象间的相互作用。适用场景 在面向对象编程中,一个类必然会与其他的类发生依赖关系,完全独立的类是没有意义的。一个类同时依赖多个类的情况也相当普遍,既然存在这样的情况,说明,一对多的依赖关系有它的合理性,适当的使用桥接模式可以使原本凌乱的对象关系清晰,但是如果滥用,则可能会带来反的效果。一般来说,只有对于那种同事类之间是网状结构的关系,才会考虑使用桥接模式。可以将网状结构变为星状结构,使同事类之间的关系变的清晰一些。 桥接模式是一种比较常用的模式,也是一种比较容易被滥用的模式。对于大多数的情况,同事类之间的关系不会复杂到混乱不堪的网状结构,因此,大多数情况下,将对象间的依赖关系封装的同事类内部就可以的,没有必要非引入中介者模式。滥用桥接模式,只会让事情变的更复杂。2.3.2 抽象工厂模式定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。类型:创建类模式类图:图2.7 抽象工厂模式UML图当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。抽象工厂模式的优点抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。抽象工厂模式的缺点产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。适用场景当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。第3章 跨平台库的设计第3章提出了编写跨平台软件的解决方案。在开始小节提供这篇论文的想法背后的动机。而第2小节给出的解决方案的概述,简称为核心和路由器。第3小节提供信息和核心的实例,和最后一小节提供了一个路由器的信息和实例。3.1 介绍从第2章中提出的实用跨平台软件开发的需求,要求必须要有更好的方法编写跨平台代码。在几种流行开源库中方法主要需求目的有不同的侧重点,很难具备到方方面面,本文侧重于需要代码满足统两条特性,可读性的结构和代码共享。换句话说,一种好的编程方法将不得不回答这个问题:“怎么能提高代码的可读性,代码共享最大化,同时保持软件组织结构清晰?”而解决方案根据情况可以分为两个开发解决方案,简称作为核心和路由。这些其实都是两种设计结构,旨在面向对象的实现。从以上的开源库中用+编写的API,并在实际的软件开发项目中使用它是显示的调用,由此就希望库程序可以更加更容易阅读和理解,而在代码共享的平台考虑被最大化。这其实是希望可以通过一种简单而对称的结构(这有助于更快地学习和记忆),允许更一致,更顺畅,“统一”的方式编写跨平台的面向对象库代码。因此核心和路由的概念被引入。3.2 核心和路由概述一个核心是一个通用的代码开发主要设计结构,可以使用UML符号来表示,如下图所示。在此图中一类用于跨平台的开发依赖于抽象类A类核心的服务,反过来,核心依赖于平台的实现在子类中平台1类核心类和平台2核心类,因此独立于平台的服务和依赖于平台的实现彻底分离的实现。因为,一般来说,大部分的基础(基础)为所有跨平台的软件代码是被包含在内核,因此用核心来彰显其务实的意义。图3.1 核心结构设计的UML图在实际应用中,我们提出的通用核心解决方案包括一个包装类,一个抽象的核心类(独立于平台的服务),以及一组的子核心类(实现依赖于平台提供的服务方法)。本论文在3.3节中使用的核心解决方案的一个例子。而另外一种跨平台软件开发方法是路由,路由是一个通用代码的开发解决方案,使用UML符号如下图所示。在此图中,B类用于跨平台软件开发服务的依赖,反过来,是与平台相关的实现类1号平台B级路由器,2号平台B级路由器等具体类B级路由器核心解决方案,这依赖于聚合和其组件类之间的继承关系,是基于路由的解决方案依赖(“使用”)类之间的关系。图3.2 路由结构设计的UML图在实际应用中,我们提出的通用路由器解决方案包括类,(主)的路由器类和一组分支路由器类(依赖于平台的方式实现服务)。关于所使用的术语路由器的选择,因为它的设计强调了从包装到对适当的实现是通过路由到所需的服务。从技术上来讲,使用几个宏可以消除主路由器类的存在,但是这将产生负面的编程风格,复杂的一致性和混乱的源代码结构(类似跨整个项目之间的H文件和cpp文件)。核心路由器借用概念的桥接模式和工厂模式。内核采用工厂设计模式的实现类的实例化。核心和路由依靠桥接的设计模式中实现特定于平台的实现的请求。对于总结介绍的关键概念,使用核心和路由的规则如下: 核心的解决方案,在实现时会使用一些特定的成员变量和对象是依赖于平台的。路由的解决方案,一个类的所有成员变量与平台无关的,但一些方法是依赖于平台的。3.3 应用范例几乎所有的操作系统使用都使用文件夹,并允许文件夹命名使用标准的字符串表示。在linux操作系统中,实现了两类对文件IO的管理,一类是遵循POSIX标准,linux操作系统自身提供的IO系统调用,如open、close、 read等函数;另一类是由ANSI标准提供的标准IO库函数,这些函数是对直接IO系统调用的封装,其在访问文件时根据需要设置了不同类型的缓冲区,从而减少了直接IO系统调用的次数,提高访问效率。然而,常见的操作之一希望在任何平台都可以统一的方法遍历文件。例如,要确定一个POSIX文件系统上的目录中的所有文件,将使用opendir,readdir,closedir函数调用的。但是在Win32文件系统,将使用FindFirstFile,FindNextFile,FindClose功能的调用。仔细分析Win32系统和Posix系统在文件操作方面,C语言提供的文件操作的确可以跨平台,但是由于系统的存储目录方式没有统一标准,所以对与文件夹的处理必须有系统来提供接口,而系统接口也比较方便,可以直接提供文件的路径就可以操作,因此并没有特定的平台数据类型,因此可以直接使用路由结。直观的使用路由可以编写一个文件操作类。一个有用的文件类将包含几个操作,但为了简便起见,我们这个例子的范围限制到一个构造函数,析构函数,判断是否为文件夹功能,而其它的关于文件操作的功能,可以借用语言本身提供的操作功能,语言的标准库本来就已经是跨平台的,先来看看最直接的实现,不使用路由结构。#include #ifdef _POSIX#include #include #include #elif defined(_WIN32)#include #include #else#error Couldnt detect correct OS#endifusing namespace std;/ File class, similar to java.io.File, though lacking functionalityclass File protected:string path; / the path to the filepublic:inlineFile(const string & filePath) : path(filePath) inline virtual File() / ensure that aFileis a directoryinline bool isDirectory() const #ifdef _POSIX / if on posix systemstruct stat sbuf;if (stat(path.c_str(), &sbuf) = -1) return false;return (sbuf.st_mode & _S_IFDIR)!=0;#elif defined(_WIN32)struct _stati64 sbuf;if (_stati64(path.c_str(), &sbuf)=-1) return false;return (sbuf.st_mode & _S_IFDIR)!=0;#endif/ make sure that a file existsinline bool exists() const #ifdef _POSIX / if on posixstruct stat sbuf;return stat(path.c_str(), &sbuf)!=-1;#elif defined(_WIN32)return GetFileAttributes(path.c_str() != INVALID_FILE_ATTRIBUTES;#endif;图3.3 无路由结构文件类定义上面的实现结构,不容易看出类的结构,也不利于扩展性。PosixFileRouter类实现如下图所示。我们可以实现将文件路由到Win32或POSIX文件路由系统。 与核心相比较,它会有较少的工作量,但同样可以达到跨平台效果,路由可以被真正的认为讲消息路由到相应的方法。从设计水平的角度来看,整个路由器的解决方案文件UML符号如图所示。从这个图中可以看到,这是一个特定的应用程序的通用路由器设计。图3.5 文件类路由UML图#include #include / Platform-independent wrapper for the FileRouter class class File protected:std:string path;public:/ Simply pass off all operations to the FileRouter classinlineFile(const std:string & filePath) : path(filePath) inlineFile()inline bool exists()const return FileRouter:exists(path);inline bool isDirectory() const return FileRouter:isDirectory(path); ;图3.4 文件类定义#include / Class to handle all File operations in a platform-dependent manner class FileRouter public:static bool exists(const std:string & path);static bool isDirectory(const std:string & path);图3.5 文件系统定义/ Check to make sure that the user wants a Posix compatible implementation#ifdef USE_POSIXFILEROUTER#include #include / check to see if a file (path) is a directorybool FileRouter:isDirectory(const std:string & path) struct _stat sbuf;if (stat(path.c_str(), &sbuf) = -1) return false;return (sbuf.st_mode & S_IFDIR) != 0;/ check to see if a file (path) existsbool FileRouter:exists(const std:string & path) struct stat sbuf;图3.6 Posix文件系统定义第4章 跨平台线程库的设计和实现在各种现代操作系统中, 线程是程序执行流的最小单元, 合理使用好线程, 可以最大程度地发挥多核处理器的性能. 但是线程的掌握和使用有很多操作系统级的概念, 这给线程使用者带来了复杂度,而且不同操作系统的本地线程库及同一操作系统的不同本地线程库都具有自己的一些API, 这些API 的接口特性总有一些差异, 这也给多线程程序的跨平台移植,以及在云计算平台中的应用带来了困难. 根据上面的分析可得, 建立本地线程库封装层, 抽象出线程及同步的基本操作是构建通用线程库的首要条件. 在构建了抽象的线程及同步的基本操作后, 这只是帮助线程使用者解决了跨平台问题, 还有很多的线程管理和其它高级的同步原语需要在这些基本操作的基础上进行合理的组合应用, 才能真正意义上实现通用线程库。4.1 线程跨平台的基础在多线程OS中,通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。线程具有以下属性。1)轻型实体线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源,比如,在每个线程中都应具有一个用于控制线程运行的线程控制块TCB,用于指示被执行指令序列的程序计数器、保留局部变量、少数状态参数和返回地址等的一组寄存器和堆栈。2)独立调度和分派的基本单位。在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小。3)可并发执行。在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行。4)共享进程资源。在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。因此线程是必不可少的元素,几乎每一个操作系统都提供了此操作,但到目前为止是没有标准的线程包(虽然POSIX委员会一直试图着手创建一个)。大多数UNIX平台上有自己的线程库,几乎所有的Linux使用POSIX线程(pthread线程库),目前微软Windows使用Win32线程。所有这些线程使用平台特定的数据类型,例如POSIX线程使用的pthread_t,而Win32线程使用Handle,因此在多线程编程中就限制了代码移植的难度。4.2总体框架设计通用线程库框架主要围绕以下两个要点进行设计.1) 对各种本地线程库的封装. 这一层的设计目标: 线程、同步原语的各种操作的抽象接口定义, 达到隔离各种本地线程库的依赖. 设计原则: 不损失操作的性能;线程主要功能的接口定义功能接口定义线程创建INT CreateThread (ThreadHandle , ExecFunc , ThreadAttr )线程终止INT ExitThread (ThreadExitCode , ExecFunc )INT TerminateThread(ThreadHandle , ThreadExitCode , ClearFunc )等待线程终止INT WaitThreadEnd(ThreadHandle , ThreadExitCode* )线程标识获取/比较ThreadHandle GetThreadHandle()BOOL CompareTH (ThreadHandle , ThreadHandle )线程属性INT InitThreadAttr(ThreadAttr ) INT DestoryThreadAttr(ThreadAttr ) INT SetThreadAttr(ThreadAttr ) INT GetThreadAttr(ThreadAttr )线程同步互斥锁INT CreateMutex(Mutex , SyncAttr ) INT DestoryMutex(Mutex ) INT LockMutex (Mutex ) INT TryLockMutex(Mutex )INT LockTimeOutMutex(Mutex ) INT UnLockMutex(Mutex )条件变量INT CreateCond(Cond , SyncAttr ) INT DestoryCond(Cond ) INT Wait (Cond ) INT WaitTiemOut(Cond )INT Signal(Cond ) INT Broadcast(Cond )同步属性INT InitThreadAttr(SyncAttr ) INT DestoryThreadAttr(SyncAttr ) INT SetSyncAttr(SyncAttr ) INT G
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国漏磁检验市场需求规模分析与投资风险监测报告
- 2025-2030环境监测设备微型化智能化发展趋势与数据应用场景
- 2025-2030牛肉期货市场发展现状与套期保值策略报告
- 2025-2030民宿短租平台商业模式及融资策略研究
- 佛山市南海区狮山镇英才学校招聘教师笔试真题2024
- 2020-2025年证券从业之金融市场基础知识题库检测试卷A卷附答案
- R-Sulindac-d6-生命科学试剂-MCE
- Metoprine-Standard-生命科学试剂-MCE
- 2025公务员国考测试题及答案
- 八年级语文下册第三单元口语交际讲一则古人故事全国公开课一等奖百校联赛微课赛课特等奖
- 产品方案设计模板
- 产科手术麻醉
- 【初中物理】质量与密度练习题 2024-2025学年初中物理人教版八年级上册
- 新时代青年做好新时代使命担当人
- 2-U9C操作培训-MRP运算
- 【上海市塑料探究所企业员工激励机制存在的问题及优化建议探析(论文)8200字】
- 浙教版二年级下册递等式计算题100道及答案
- 安全管理核心制度综合体系华润置地北京
- 《核电厂汽轮发电机组隔振基础测试技术导则》
- 第八章-高级土壤化学之土壤的氧化还原化学
- 市政工程方案设计
评论
0/150
提交评论