云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > darwin分析

darwin分析

  • 62 次阅读
  • 3 次下载
  • 2025/5/4 19:53:30

Darwin 5.5.5 代码分析文档 ---sinkin(jinzhcheng@tom.com) 2007.10

DarwinStreamServer是苹果公司开发的流媒体视频服务器。我们分析的代码基于版本5.5.5。

一、DSS启动、初始化流程

我们从Server.tproj/main.cpp入手,分析DSS加载module及和module交互的流程。 (1)、DSS在fork子进程后调用StartServer启动服务

调用OS、OSThread、Socket、SocketUtils、QTSSDictionaryMap、 QTSServerInterface、QTSServer等类的Initialize函数进行初始化。

(2)、select_startevents函数

initialize the select() implementation of the event queue. (3)、QTSServer::Initialize函数

继续调用QTSSModule、QTSServerPres、QTSSMessages、RTSPRequestInterface、 RTSPSessionInterface、RTPSessionInterface、RTPStream、RTSPSession、 QTSSFile、QTSSUserProfile等类的Initialize函数,进行dictionary的初始化。 加载了第一个模块QTSSErrorLogModule。 this->SetDefaultIPAddr() // set default IP addr & DNS name

// begin listening,注意这里传的是false参数。

this->CreateListeners(false,fSrvrPrefs,inPortOverride)

(4)、TaskThreadPool::AddThreads(numThreads) // numThreads为 1

到这里,第一个线程创建、运行、被添加到线程池里。

在startBroadcastRTSPSession函数里,又调用AddThreads函数在线程池里添加了一个线程。

(5)、TimeoutTask::Initialize()

Start up the server's global tasks, and start listening. The timeoutTask mechanism is task based, we therefore must do this after adding task threads. This be done before starting the sockets and server tasks.

sThread = NEW TimeoutTaskThread(); sThread->signal(Task::kStartEvent);

创建一个TimeoutTaskThread类对象,实际上这个类的名字容易产生混淆,它并不是一个线程类,而是一个基于Task类的任务类。

因为前面已经在线程池里添加了一个任务线程,所以在这里调用signal的时候,就会找到这个线程, 并把事件加入到这个线程的任务队列里,等待被处理。(这时,刚才创建的线程应该也在 TaskThread::Entry函数里等待事件的发生)

(6)、IdleTask::Initialize()

// 创建并启动空闲任务线程

sIdleThread = NEW IdleTaskThread();

sIdleThread->Start();

(7)、Socket::StartThread()

// 启动Socket类的sEventThread类所对应的线程。sEventThread类在Socket::Initialize函数里创建 // 到目前为止,这已是第三个启动的线程,分别是任务线程、空闲任务线程、事务线程。

(8)、OSThread::Sleep(1000)

这里的Sleep是调用usleep来实现,为什么这里要睡眠1s???是为了等待线程的启动???

(9)、sServer->InitModules(inInitialState) 初始化并加载一些模块。共加载了 QTSSHomeDirectoryModule、QTSSRefMovieModule、QTSSFileModule、QTSSReflectorModule、 QTSSRelayModule、QTSSAccessLogModule、QTSSFlowControlModule、QTSSPosixFileSysModule、 QTSSAdminModule、QTSSMP3StreamingModule、QTSSAccessModule这些模块。 fSrvrPrefs = new QTSServerPrefs(sPrefsSource, true); ... ... fSrvrM7essages = new QTSSMessages(sMessagesSource); QTSSModuleUtils::Initialize(fSrvrMessages, this, QTSServerInterface::GetErrorLogStream()); ... ... Add Reread Preferences Service. // 对于那些支持initial role的模块,通过它们的CallDispatch函数来调用具体的initial函数。 this->DoInitRole(); (10)、sServer->StartTasks() 创建RTCPTask、RTPStatsUpdaterTask Start listening,因为TCPListenerSocket是EventContext的继承类,所以这里实际上调用的是 EventContext::RequestEvent().

(11)、sServer->SetupUDPSockets()

udp sockets are set up after the rtcp task is instantiated。

针对系统的每一个ip地址,都创建并绑定一个socket端口对(分别用于RTP data发送和RTCP data接 收),并申请对这两个socket端口的监听。

注意调用CreateUDPSocketPair函数传进去的Port参数为0,所以在通过Darwin播放静态多媒体文件 时,不论是同一个媒体文件的音频、视频流还是同时播放的多个媒体文件,都是这两个socket端口 来完成RTCP、RTP数据的处理。

(12)、CleanPid(true);

在/var/run下写pid文件

WritePid(!inDontFork); doneStartingUp = true;

(13)、sServer->SwitchPersonality()

switch to run user and group ID 执行setgid、setuid函数

(14)、RunServer()

由一个大循环构成:

while((theServerState != qtssShuttingDownState) && (theServerState != qtssFatalErrorState)) { OSThread::Sleep(1000); if(sStatusUpdateInterval) // 周期性更新状态,当带有-D参数时,为3。 { 通过PrintHeader打印标题行

RTP-Conns RTSP-Conns HTTP-Conns kBits/Sec Pkts/Sec RTP-Playing AvgDelay CurMaxDelay MaxDelay AvgQuality NumThinned Time RTP-Conns RTSP-Conns HTTP-Conns kBits/Sec Pkts/Sec TotConn TotBytes TotPktsLost Time

通过DebugLevel_1、PrintStatus打印每字段的值。 每个字段对应的变量分别为: RTP-Conns: fNumRTPSessions; RTSP-Conns: fNumRTPSessions;

HTTP-Conns: fNumRTSPHTTPSessions; kBits/Sec: fCurrentRTPBandwidthInBits; Pkts/Sec: fRTPPacketsPerSecond; RTP-Playing: fNumRTPPlayingSessions;

// sLastDebugPacket即为上次的fTotalRTPPackets。 AvgDelay: fTotalLate/(fTotalRTPPackets – sLastDebugPackets) CurMaxDelay: fCurrentMaxLate; MaxDelay: fMaxLate;

// sLastDebugTotalQuality即为上次的fTotalQuality。 AvgQuality: (fTotalQuality-sLastDebugTotalQuality)/(fTotalRTPPackets–sLastDebugPackets) NumThinned: fNumThinned; TotConn: TotBytes: TotPktsLost:

fTotalRTPSessions; fTotalRTPBytes;

fTotalRTPPacketsLost

}

如果接收到SigInt或者SigTerm,则终止sServer。

二、几大部分

(一)、模块

? DSS利用模块来响应请求和处理任务。DSS的模块分为三种类型: (1)、Content-Managing Modules

The content-managing modules manage RTSP requests and responses related to media sources, such as a file or a broadcast. Each module is responsible for interpreting the client's request, reading and parsing their supported files or network source, and responding with RTSP and RTP. In some cases, such as the mp3 streaming module, the module uses HTTP. The content-managing modules are QTSSFileModule, QTSSReflectorModule, QTSSRelayModule, and QTSSMP3StreamingModule.

(2)、Server-Support Modules

The server-support modules performserver data gathering and logging functions. The server- support modules are QTSSErrorLogModule, QTSSAccessLogModule, QTSSWebStatsModule, QTSSWebDebugModule, QTSSAdminModule, and QTSSPOSIXFileSystemModule.

(3)、Access Control Modules

The access control modules provide authentication and authorization functions as well as URL path manipulation. The access control modules are QTSSAccessModule, QTSSHomeDirectoryModule, QTSSHttpFileModule, and QTSSSpamDefenseModule.

?

几个相关类的定义 一、QTSSModule类

各个Module类均以QTSSModule类为基类。

(1)、构建函数

?

QTSSModule::QTSSModule(char* inName, char* inPath)

: QTSSDictionary(QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kModuleDictIndex)), ... ... { 如果模块以库文件的形式保存在disk上,利用OSCodeFragment类来处理 另外,QTSSModule本身是QTSSDictionary的继承类,它还有一个QTSSDictionary类对象的指 针成员 调用SetVal、SetValue进行一些属性的设置 }

模块加载过程

一、以加载QTSSErrorLogModule为例

在创建一个QTSSModule类对象后,调用该类的SetupModule成员函数,并调用AddModule函数和调用QTSServer的BuildModuleRoleArrays函数。

注意:DSS还提供了一个OSCodeFragment类,来处理以库文件的形式保存在disk的模块。 (1)SetupModule成员函数

传给SetupModule成员函数的两个形参分别是QTSS_CallbacksPtr(函数指针)、

QTSS_MainEntryPointPtr(具体模块的进入函数指针,对于QTSSErrorLogModule类,这个函数是QTSSErrorLogModule_Main) 调用QTSSErrorLogModule_Main

_stublibrary_main(inPrivateArgs, QTSSErrorLogModuleDispatch) sCallbacks = theArgs->inCallbacks;

sErrorLogStream = theArgs->inErrorLogStream; // Send requested information back to the server theArgs->outStubLibraryVersion = QTSS_API_VERSION; theArgs->outDispatchFunction = inDispatchFunc; 注:这里的sCallbacks、sErrorLogStream分别是在QTSS_Private.cpp里定义的静 态全局量。theArgs->inCallbacks为SetupModule的实参(即QTSServer类的 sCallbacks成员),而inDispatchFunc为具体模块传进来的实参 QTSSErrorLogModuleDispatch。

将fDispatchFunc设置为thePrivateArgs.outDispatchFunction,fDispatchFunc为QTSSModule的私有类成员。这样DSS可以通过具体模块的基类QTSSModule的这个私有成员来让具体模块进行分发处理。 调用QTSServerInterface::LogError函数进行log功能。

(2)AddModule函数

传给AddModule函数的实参为要加载的具体模块。

Prepare to invoke the module's Register role. Setup the Register param block QTSS_ModuleState theModuleState; theModuleState.curModule = inModule;

theModuleState.curRole = QTSS_Register_Role; theModuleState.curTask = NULL;

OSThread::SetMainThreadData(&theModuleState);

inModule->CallDispatch(QTSS_Register_Role, &theRegParams); (fDispatchFunc)(inRole, inParams); 对于QTSSErrorLogModule模块即为QTSSErrorLogModuleDispatch函数,该函数根据不同的 Role调用模块具体的处理函数,对于QTSS_Register_Role调用Register函数。Register函 数通过调用QTSS_AddRole来告知DSS模块支持的Role。

// Update the module name to reflect what was returned from the register role

inModule->SetValue(qtssModName, 0, theRegParams.regParams.outModuleName, ::strlen(theRegParams.regParams.outModuleName), false);

// Give the module object a prefs dictionary. Instance attributes are allowed for these objects. QTSSPrefs* thePrefs = NEW QTSSPrefs( sPrefsSource, inModule->GetValue(qtssModName), QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kModulePrefsDictIndex), true); thePrefs->RereadPreferences(); inModule->SetPrefsDict(thePrefs);

// Add this module to the array of module (dictionaries)

UInt32 theNumModules = this->GetNumValues(qtssSvrModuleObjects);

QTSS_Error theErr = this->SetValue(qtssSvrModuleObjects, theNumModules, &inModule, sizeof(QTSSModule*), QTSSDictionary::kDontObeyReadOnly); // Add this module to the module queue

sModuleQueue.EnQueue(inModule->GetQueueElem());

(3)BuildModuleRoleArrays函数

根据QTSSModule的fRoleArray数组的Role支持情况,在QTSServerInterface::sNumModulesInRole里做记录,并在sModuleArray数组里保存相关Role的所有QTSSModule指针。 这样,QTSServer就可以知道目前有哪些模块支持哪些Role。

到此,一个Module已经添加到QTSServer里。

二、以加载QTSSReflectorModule为例

在创建一个QTSSModule类对象后,调用该类的SetupModule成员函数,并调用AddModule函数和调用QTSServer的BuildModuleRoleArrays函数。

搜索更多关于: darwin分析 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

Darwin 5.5.5 代码分析文档 ---sinkin(jinzhcheng@tom.com) 2007.10 DarwinStreamServer是苹果公司开发的流媒体视频服务器。我们分析的代码基于版本5.5.5。 一、DSS启动、初始化流程 我们从Server.tproj/main.cpp入手,分析DSS加载module及和module交互的流程。 (1)、DSS在fork子进程后调用StartServer启动服务 调用OS、OSThread、Socket、SocketUtils、QTSSDictionaryMap、 QTSServerInterface、QTSServer等类的Initialize函数进行初始化。

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com