深入剖析NS2的框架代码.docx
《深入剖析NS2的框架代码.docx》由会员分享,可在线阅读,更多相关《深入剖析NS2的框架代码.docx(16页珍藏版)》请在冰豆网上搜索。
深入剖析NS2的框架代码
1. NS2的主函数main位于tclAppInit.cc文件中
int
main(intargc,char**argv
{
Tcl_Main(argc,argv,Tcl_AppInit;
return0; /*Neededonlytopreventcompilerwarning.*/
}
从这个main函数中我们可以看到:
整个NS2的框架其实完全包含在TCL_Main函数中。
2.Tcl_Main函数位于/generic/TclMain.c文件中,这个函数的代码如下:
(可能比较长)
void
Tcl_Main(argc,argv,appInitProc
intargc; /*Numberofarguments.*/
char**argv; /*Arrayofargumentstrings.*/
Tcl_AppInitProc*appInitProc;
/*Application-specificinitialization
*proceduretocallaftermost
*initializationbutbeforestartingto
*executecommands.*/
{
Tcl_Obj*resultPtr,*argvPtr,*commandPtr=NULL;
PromptTypeprompt=PROMPT_START;
intcode,length,tty,exitCode=0;
Tcl_ChannelinChannel,outChannel,errChannel;
Tcl_Interp*interp;
Tcl_DStringappName;
Tcl_Obj*objPtr;
Tcl_FindExecutable(argv[0]; //寻找可执行文件ns?
作用未知,参数的值为可执行文件ns对应的路径
interp=Tcl_CreateInterp(; //创建OTCL解释器
Tcl_InitMemory(interp; //配置解释器
/*
*Makecommand-lineargumentsavailableintheTclvariables"argc"
*and"argv".Ifthefirstargumentdoesn'tstartwitha"-"then
*stripitoffanduseitasthenameofascriptfiletoprocess.
*/
if(TclGetStartupScriptPath(==NULL{
if((argc>1&&(argv[1][0]!
='-'{
TclSetStartupScriptFileName(argv[1];
argc--;
argv++;
}
}
if(TclGetStartupScriptPath(==NULL{
Tcl_ExternalToUtfDString(NULL,argv[0],-1,&appName;
}else{
TclSetStartupScriptFileName(Tcl_ExternalToUtfDString(NULL,
TclGetStartupScriptFileName(,-1,&appName;
}
Tcl_SetVar(interp,"argv0",Tcl_DStringValue(&appName,TCL_GLOBAL_ONLY;
Tcl_DStringFree(&appName;
argc--;
argv++;
objPtr=Tcl_NewIntObj(argc;
Tcl_IncrRefCount(objPtr;
Tcl_SetVar2Ex(interp,"argc",NULL,objPtr,TCL_GLOBAL_ONLY;
Tcl_DecrRefCount(objPtr;
argvPtr=Tcl_NewListObj(0,NULL;
while(argc--{
Tcl_DStringds;
Tcl_ExternalToUtfDString(NULL,*argv++,-1,&ds;
Tcl_ListObjAppendElement(NULL,argvPtr,Tcl_NewStringObj(
Tcl_DStringValue(&ds,Tcl_DStringLength(&ds;
Tcl_DStringFree(&ds;
}
Tcl_IncrRefCount(argvPtr;
Tcl_SetVar2Ex(interp,"argv",NULL,argvPtr,TCL_GLOBAL_ONLY;
Tcl_DecrRefCount(argvPtr;
/*
*Setthe"tcl_interactive"variable.
*/
tty=isatty(0;
Tcl_SetVar(interp,"tcl_interactive",
((TclGetStartupScriptPath(==NULL&&tty?
"1":
"0",
TCL_GLOBAL_ONLY;
/*
*Invokeapplication-specificinitialization.
*/
Tcl_Preserve((ClientDatainterp;
if((*appInitProc(interp!
=TCL_OK{ //此处的appInitProc具体实现见于TclAppInit.cc,为了方便,将其代码展示如下:
********************************************************************************************************************************
int
Tcl_AppInit(Tcl_Interp*interp
{
#ifdefMEMDEBUG_SIMULATIONS
externMemTrace*globalMemTrace;
globalMemTrace=newMemTrace;
#endif
setup_floating_point_environment(;
if(Tcl_Init(interp==TCL_ERROR||
Otcl_Init(interp==TCL_ERROR
returnTCL_ERROR;
#ifdefHAVE_LIBTCLDBG
externintTcldbg_Init(Tcl_Interp*; //hackorama
if(Tcldbg_Init(interp==TCL_ERROR{
returnTCL_ERROR;
}
#endif
Tcl_SetVar(interp,"tcl_rcFileName","~/.ns.tcl",TCL_GLOBAL_ONLY;
Tcl:
:
init(interp,"ns";//Tcl:
init会调用到TclClass:
init,而后者完成的任务,主要是将通过调用依次调用所有在main函数前创建的全局TclClass静态实例的bind函数。
而bind函数只在祖先类TclClass中实现了(特殊的是PacketHeaderClass类,它有自己的实现,但也事先调用了TclClass类的实现,其子类亦无实现。
TclClass的bind函数所完成的任务便是根据所有静态实例存储的OTCL类名(定义时拟好的参数,创建相对应的OTCL类,并添加create-shadow和delete-shadow命令。
具体代码见TclClass:
:
bind(
init_misc(;
et_ns_ptypes.load(;
et_ns_lib.load(; //et_ns_lib是一个EmbeddedTcl类,它的私有成员constchar*code_在文件ns_tcl.cc中,被初始化为NS2所需要的所有OTCL类定义串联成的一个巨型字符串(这个字符串是在Makefile中通过将ns-lib.tcl中定义以及用source语句引用的其它tcl文件所对应的源文件全部拷贝并串联起来,生成后导入到ns_tcl.cc中的。
查看ns_tcl.cc的文件中的code_值,我们便可以知道NS2在初始化时建立的所有OTCL对象。
//et_ns_lib.load(其实现为:
/*voidEmbeddedTcl:
:
load(
{
Tcl:
:
instance(.evalc(code_;
}*/
//这个函数所完成的工作,便是将code_存储的所有NS相关的OTCL定义,用新建立起来的tcl环境对其进行解释,并建立相应的OTCL环境。
#ifdefTCL_TEST
if(Tcltest_Init(interp==TCL_ERROR{
returnTCL_ERROR;
}
Tcl_StaticPackage(interp,"Tcltest",Tcltest_Init,
(Tcl_PackageInitProc*NULL;
#endif/*TCL_TEST*/
returnTCL_OK;
}
********************************************************************************************************************************
errChannel=Tcl_GetStdChannel(TCL_STDERR;
if(errChannel{
Tcl_WriteChars(errChannel,
"application-specificinitializationfailed:
",-1;
Tcl_WriteObj(errChannel,Tcl_GetObjResult(interp;
Tcl_WriteChars(errChannel,"\n",1;
}
}
if(Tcl_InterpDeleted(interp{
gotodone;
}
/*
*Ifascriptfilewasspecifiedthenjustsourcethatfile
*andquit.
*/
if(TclGetStartupScriptPath(!
=NULL{
code=Tcl_FSEvalFile(interp,TclGetStartupScriptPath(;
if(code!
=TCL_OK{
errChannel=Tcl_GetStdChannel(TCL_STDERR;
if(errChannel{
/*
*ThefollowingstatementguaranteesthattheerrorInfo
*variableissetproperly.
*/
Tcl_AddErrorInfo(interp,"";
Tcl_WriteObj(errChannel,Tcl_GetVar2Ex(interp,"errorInfo",
NULL,TCL_GLOBAL_ONLY;
Tcl_WriteChars(errChannel,"\n",1;
}
exitCode=1;
}
gotodone;
}
/*
*We'rerunninginteractively.Sourceauser-specificstartup
*fileiftheapplicationspecifiedoneandifthefileexists.
*/
Tcl_SourceRCFile(interp;
/*
*Processcommandsfromstdinuntilthere'sanend-of-file.Note
*thatweneedtofetchthestandardchannelsagainafterevery
*eval,sincetheymayhavebeenchanged.
*/
commandPtr=Tcl_NewObj(;
Tcl_IncrRefCount(commandPtr;
/*
*Getanewvalueforttyifanyonewritesto:
:
tcl_interactive
*/
Tcl_LinkVar(interp,"tcl_interactive",(char*&tty,TCL_LINK_BOOLEAN;
inChannel=Tcl_GetStdChannel(TCL_STDIN;
outChannel=Tcl_GetStdChannel(TCL_STDOUT;
while((inChannel!
=(Tcl_ChannelNULL&&!
Tcl_InterpDeleted(interp{
if(mainLoopProc==NULL{
if(tty{
Prompt(interp,&prompt;
if(Tcl_InterpDeleted(interp{
break;
}
inChannel=Tcl_GetStdChannel(TCL_STDIN;
if(inChannel==(Tcl_ChannelNULL{
break;
}
}
if(Tcl_IsShared(commandPtr{
Tcl_DecrRefCount(commandPtr;
commandPtr=Tcl_DuplicateObj(commandPtr;
Tcl_IncrRefCount(commandPtr;
}
length=Tcl_GetsObj(inChannel,commandPtr;
if(length<0{
if(Tcl_InputBlocked(inChannel{
/*
*Thiscanonlyhappenifstdinhasbeensetto
*non-blocking.Inthatcasecyclebackandtry
*again.Thissetsupatightpollingloop(since
*wehavenoeventlooprunning.Ifthiscauses
*badCPUhogging,wemighttrytogglingtheblocking
*onstdininstead.
*/
continue;
}
/*
*EitherEOF,oranerroronstdin;we'redone
*/
break;
}
/*
*AddthenewlineremovedbyTcl_GetsObjbacktothestring.
*/
if(Tcl_IsShared(commandPtr{
Tcl_DecrRefCount(commandPtr;
commandPtr=Tcl_DuplicateObj(commandPtr;
Tcl_IncrRefCount(commandPtr;
}
Tcl_AppendToObj(commandPtr,"\n",1;
if(!
TclObjCommandComplete(commandPtr{
prompt=PROMPT_CONTINUE;
continue;
}
prompt=PROMPT_START;
code=Tcl_RecordAndEvalObj(interp,commandPtr,TCL_EVAL_GLOBAL;
inChannel=Tcl_GetStdChannel(TCL_STDIN;
outChannel=Tcl_GetStdChannel(TCL_STDOUT;
errChannel=Tcl_GetStdChannel(TCL_STDERR;
Tcl_DecrRefCount(commandPtr;
commandPtr=Tcl_NewObj(;
Tcl_IncrRefCount(commandPtr;
if(code!
=TCL_OK{
if(errChannel{
Tcl_WriteObj(errChannel,Tcl_GetObjResult(interp;
Tcl_WriteChars(errChannel,"\n",1;
}
}elseif(tty{
resultPtr=Tcl_GetObjResult(interp;
Tcl_IncrRefCount(resultPtr;
Tcl_GetStringFromObj(resultPtr,&length;
if((length>0&&outChannel{
Tcl_WriteObj(outChannel,resultPtr;
Tcl_WriteChars(outChannel,"\n",1;
}
Tcl_DecrRefCount(resultPtr;
}
}else{ /*(mainLoopProc!
=NULL*/
/*
*Ifamainloophasbeendefinedwhilerunninginteractively,
*wewanttostartafileeventbasedpromptbyestablishinga
*channelhandlerforstdin.
*/
InteractiveState*isPtr=NULL;
if(inChannel{
if(tty{
Prompt(interp,&prompt;
}
isPtr=(InteractiveState*
ckall