您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 销售管理 > Darwin Streaming Server通用服务器处理机制
NSS通用服务器处理机制1概述通用服务器处理机制是指一套以C++编写的实现一般服务器程序通常都要实现的程序框架。NSS服务器处理机制实现了这个框架,这个程序框架封装了常用的C++的技术应用,如线程,信号,内存,SOCKET传输等。在这个框架基础进行开发可以快速建立一套服务器程序,使开发人员更专注于应用逻辑的开发。NSS通用服务器处理机制源于Apple公司开源项目DarwinStreamingServer.一个流媒体服务器程序,我们将其对服务器程序的处理部分独立出来进行必要的修改组成现在的处理机制。在此框架上建立的服务器程序同时支持FreeBSD、Linux、Solaris、WindowsNT和Windows2000等多个操作系统。2组成整个处理框架被封装成一个静态库.很容易被集成进新的项目。CommonUtilitiesLib目录下所有文件即为静态库源码。在WIN32下应用时可将其下的*.dsw添入工程。然后在需要引用该库的工程中引入。以VC6为例,Project-Dependencies下选择CommonUtilitiesLib.在Linux下在链接选项添加–lCommonUtilitiesLib参数链接进工程。CommonUtilitiesLib目录下源代码完全采用标准C++语言写成,编程风格非常优秀,每个C++类都对应着一对和类同名的.h/.cpp文件。大量采用了面向对象的概念,如继承、多态等等.3代码分析3.1基础功能类3.1.1OS类DSS支持包括Windows,Linux以及Solaris在内的多种操作系统平台。我们知道,Windows和Unix(或Unix-like)操作系统之间无论从内核还是编程接口上都有着本质的区别,即使是Linux和Solaris,在编程接口上也大为不同。为此,DSS开发了多个用于处理时间、临界区、信号量、事件、互斥量和线程等操作系统相关的类,这些类为上层提供了统一的使用接口,但在内部却需要针对不同的操作系统采用不同的方法实现。以下列出了DSS中的主要OS类和数据结构及其功能。OS平台相关的功能类,如内存分配、时间等OSCond状态变量的基本功能和操作OSMutex互斥量的基本功能和操作OSThread线程类OSFileSource简单文件类OSQueue队列类OSHashTable哈希表类OSHeap堆类OSRef参考引用类3.1.2OSMutex/OSCond类在有多个线程并发运行的环境中,能同步不同线程的活动是很重要的,DSS开发了OSMutex和OSCond两个类用以封装不同操作系统对线程同步支持的差异。我们首先分析OSMutex类,这个类定义了广义互斥量的基本操作,类定义如下:classOSMutex{1public:2OSMutex();//构造函数3~OSMutex();//析构函数4inlinevoidLock();//加锁5inlinevoidUnlock();//解锁6inlineBool16TryLock();//异步锁,无论是否成功立即返回7private:8#ifdef__Win32__9CRITICAL_SECTIONfMutex;//临界区10DWORDfHolder;//拥有临界区的线程id11UInt32fHolderCount;//进入临界区线程数//其他略…}在Windows平台上,OSMutex类是通过临界区(CRITICAL_SECTION)来实现的,第10行定义了临界区变量fMutex。类实例化时构造函数调用InitializeCriticalSection(&fMutex)初始化临界区变量,对应的在析构函数中调用DeleteCriticalSection(&fMutex)清除。Lock()函数用于对互斥量加锁,它调用私有方法RecursiveLock实现:voidOSMutex::RecursiveLock(){//当前线程已经拥有互斥量,只需增加引用计数1if(OSThread::GetCurrentThreadID()==fHolder)2{3fHolderCount++;//增加引用计数4return;5}6#ifdef__Win32__7::EnterCriticalSection(&fMutex);//申请进入临界区8#else9(void)pthread_mutex_lock(&fMutex);10#endif11Assert(fHolder==0);12fHolder=OSThread::GetCurrentThreadID();//更新临界区拥有者标志13fHolderCount++;14Assert(fHolderCount==1);}第1行检测如果当前线程已经拥有互斥量,就只需将内部计数fHolderCount加1,以便纪录正在使用互斥量的方法数。如果当前线程还没有得到互斥量,第7行调用EnterCriticalSection()函数申请进入临界区;如果当前已经有其他线程进入临界区,该函数就会阻塞,使得当前线程进入睡眠状态,直到占用临界区的线程调用LeaveCriticalSection(&fMutex)离开临界区后才可能被唤醒。一旦线程进入临界区后,它将首先更新临界区持有者标志(第12行),同时将临界区引用计数加1。注意到另外一个函数TryLock(),该函数也是用于为互斥量加锁,但与Lock()不同的是,TryLock()函数为用户提供了异步调用互斥量的功能,这是因为它调用::TryEnterCriticalSection(&fMutex)函数申请进入缓冲区:如果临界区没有被任何线程拥有,该函数将临界区的访问区给予调用的线程,并返回TRUE,否则它将立刻返回FALSE。TryEnterCriticalSection()和EnterCriticalSection()函数的本质区别在于前者从不挂起线程。接着分析OSCond类,该类定义了状态变量(ConditionVariable)的基本操作,类定义如下:classOSCond{1public:2OSCond();//构造函数3~OSCond();//析构函数4inlinevoidSignal();//传信函数5inlinevoidWait(OSMutex*inmate,SInt32inTimeoutInMilSecs=0);//等待传信函数6inlinevoidBroadcast();//广播传信函数7private:8#ifdef__Win32__9HANDLEfCondition;//事件句柄10UInt32fWaitCount;//等待传信用户数//其他略…}虽然同是用于线程同步,但OSCond类与OSMutex大不相同,后者用来控制对关键数据的访问,而前者则通过发信号表示某一操作已经完成。在Windows平台中,OSCond是通过事件(event)来实现的;构造函数调用CreateEvent()函数初始化事件句柄fCondition,而析构函数则调用CloseHandle()关闭句柄。OSCond的使用流程是这样的:线程调用Wait(OSMutex*inmate,SInt32inTimeoutInMilSecs=0)函数等待某个事件的发生,其中inTimeoutInMilSecs是最长等待时间,0代表无限长。Wait()函数内部调用了WaitForSingleObject(fCondition,theTimeout)函数,该函数告诉系统线程在等待由事件句柄fCondition标识的内核对象变为有信号,参数theTimeout告诉系统线程最长愿意等待多少毫秒。如果指定的内核对象在规定时间内没有变为有信号,系统就会唤醒该线程,让它继续执行。而函数Signal()正是用来使事件句柄fCondition有信号的。Signal()函数内部实现很简单,只是简单调用SetEvent函数将事件句柄设置为有信号状态。使用OSCond的过程中存在一种需求,就是希望通知所有正在等待的用户事件已经完成,而Signal()函数每次只能通知一个用户,因此又开发了另外一个广播传信函数如下:inlinevoidOSCond::Broadcast(){//提示:本函数相当循环调用Signal()函数1#ifdef__Win32__2UInt32waitCount=fWaitCount;//等待传信的用户数3for(UInt32x=0;xwaitCount;x++)//循环为每个用户传信4{5BOOLtheErr=::SetEvent(fCondition);//设置事件句柄为有信号状态6Assert(theErr==TRUE);7}//此处略…}Broadcast首先统计所有等待传信的用户数(第2行),然后用一个循环为每个用户传信(第3~7)行。这种编程方法虽然不是很优雅(elegant),但是由于Windows平台上不支持广播传信功能(Linux和Solaris均支持),也只好如此。3.1.2OSThread类OSThread是DSS中最重要的类之一,它封装并且定义了使用线程的方式,因此需要重点讨论。OSThread类的定义如下:classOSThread{1public://必须在使用其他OSThread函数前调用该初始化函数2staticvoidInitialize();3OSThread();//构造函数4virtual~OSThread();//析构函数//子类继承该纯虚函数完成自己的工作5virtualvoidEntry()=0;6voidStart();//启动线程7voidJoin();//等待线程运行完成后删除8voidDetach();//使线程处于fDetached状态9staticvoidThreadYield();//Windows平台不用10staticvoidSleep(UInt32inMsec);//让线程睡眠…11private://标识线程的状态12Bool16fStopRequested:1;13Bool16fRunning:1;14Bool16fCancelThrown:1;15Bool16fDetached:1;16Bool16fJoined:1;…17staticvoidCallEntry(OSThread*thread);//调用子类重载的虚函数18#ifdef__Win32__//使用_beginghreadex创建线程时的标准入口函数19staticunsignedintWINAPI_Entry(LPVOIDinThread);20#else21staticvoid*_Entry(void*inThread);//unix下的入口函数22#endif}OSThread封装了线程的基本功能,一个OSThread的实例代表一个线程。用户通过继承OSThread,并且重载其中的纯虚函数Entry(第5行),从而将自己的任务交给该线程运行。OSThread内部运行机制比较复杂,为此我们用图3所示的流程来描述其运行过程。另外,OSThread对于线程的状态定义了一套完整的控制方法。当用户调用start()函数后,按照上图,最终将调用CallEntry()函数,而该函数在调用Entry()之前将线程设定为运行状态(thread-fRunning=true),当Entry()函数运行完后再设为非运行状态;在运行过程中,用户可以通过StopAndWaitForThread()、join()、Detach()以及ThrowStopRequest()等函数改变线程其他状态变量。3.1.3OSHashTable/OSQueue/OSHeap/OSRefClassDSS定义了几个通用的较为复杂的数据结构,它们都以类的方式封装。这些数据结构不但贯穿于DSS的所有源代码,而且由于其封装的十分好,读者可以在看懂源代码的基础上很容易的将它们从DSS的工程中抽取出来,构建自己的基础类库,为将来的开发工作打下良好的基础。另外,对这些基础数据结构源
本文标题:Darwin Streaming Server通用服务器处理机制
链接地址:https://www.777doc.com/doc-3439630 .html