声明
本博客中的很多术语,模型并非教科书或业界认可的,而是个人分析后根据理解所取定义的。这些术语、模型存在很多片面理解,但有助于本人对系统的理解和学习。希望观看本博客的各位朋友慎重,对大家有帮助的我感到很荣幸,有错误的,敬请批评指正。
嵌套调用的实例
一般的应用程序,都是从main()函数开始执行,在实现程序的功能时,通常每个功能都有一个入口函数,如GetFreq(),获取某个测试点的信号频率值。GetFreq()方法在实现其功能时,需要调用很多方法,比如有三个GetStepL2_1(),GetStepL2_2(),GetStepL2_3()。在这三个函数自身的实现时,也会调用其他的方法,需要不断的嵌套调用。比如GetStepL2_1()调用GetStepL3_1(),GetStepL3_2(),GetStepL3_3();GetStepL2_2()调用GetStepL3_1(),GetStepL3_2();GetStepL2_3()调用GetStepL3_1()。(注意,这里有意识的使用GetStepLx_x()这样的命名方式来区分不同深度的方法)嵌套调用的终点是调用仪器的驱动。根据嵌套的深度,可以将不同的函数归纳为不同的深度。调用深度的定义是这样的,GetFreq()为第一级,GetStepL2_1(),GetStepL2_2(),GetStepL2_3()为第二级;GetStepL3_1(),GetStepL3_2(),GetStepL3_3()为第三级,一次类推。其拓扑结构向树根的分支。
调用链模型
上例中,
GetFreq()--->GetStepL2_1()--->GetStepL3_1(),
GetFreq()--->GetStepL2_1()--->GetStepL3_2(),
GetFreq()--->GetStepL2_1()--->GetStepL3_3(),
GetFreq()--->GetStepL2_2()--->GetStepL3_1(),
GetFreq()--->GetStepL2_2()--->GetStepL3_2(),
GetFreq()--->GetStepL2_3()--->GetStepL3_1()
都是调用链,共有六条调用链,每条调用链都会对应一个调用堆栈。
当然,这些调用堆栈的拓扑结构并不是平行的,而是树状的,很多调用链都有共同的部分。
调用堆栈
在函数嵌套调用时,以函数为单元,每当有个函数被调用时,都被压入堆栈(这里不是以调用处的断点,调用者的局部变量这些方面分析,而是以整个函数为一个基本单元,压栈和出栈都是以函数为单位)。因此,形成一个函数调用堆栈。从此可以分析,位于调用堆栈栈顶的一定是调用模型中,深度最深的。比如上例中模块提供的驱动函数位于每个调用链的栈顶。在每条调用链中,GetFreq()都是位于栈底的。这和堆栈的特性一样,最晚入栈的在栈顶。