[英]What is the background process when a tcl script is run?
启动tcl脚本时,将发生什么后台进程。 (类似于c编译)?
当您启动期望时,脚本过程如何工作?
假设你已经有一个正在运行的Tcl解释,只是source
脚本来运行它(以避免描述整个翻译启动序列和初始化),下面的事情发生在任何近期(8.x的)Tcl解释。
这基本上会调用某些C代码,例如Tcl_EvalFile()
,它将脚本加载到内存中,以及实际执行内部内部TclEvalEx()
,这是TclEvalEx()
的私有版本, Tcl_EvalEx()
处所述( https ://www.tcl.tk/man/tcl/TclLib/Eval.htm )。
这无需字节码编译即可解释顶级脚本,例如,脚本被解析后,一旦找到命令,便会直接执行。 这是相当慢的,并且较老的Tcl 7.x一直都在运行。
但是,如果执行了一条命令,则会检查该命令是否可以字节编译为更有效的形式。 通过proc
定义的命令就是这种情况,因此,如果第一次执行命令,则Tcl_EvalObjEx()
会在内部调用TclCompileObj()
来获取命令的字节码表示形式,该字节码表示形式将缓存在已解析命令的Tcl_Obj
内。
如果无法编译该命令,则直接执行该命令,例如,调用generic/tclCmd*.c
中的功能之一,例如,要处理命令concat
该命令将是generic/tclCmdAH.c
Tcl_ConcatObjCmd()
。 此函数也可能来自加载到解释器中的某些C扩展,并且以完全相同的方式处理。 可用命令在内部在某些哈希表中注册,这就是Tcl_CreateObjCmd()
作用。
但是,如果可以编译该命令,则会发生一些不同的事情。 在这种情况下,该命令将转换为字节码表示形式。 例如,对于这样一个简单的过程: proc c {ab} {concat $a $b}
,它将变成四个字节码。 您实际上可以通过::tcl::unsupported::disassemble
命令检查生成的字节码,并使用Tcl 8.6.3来查看此Tkcon会话:
() 69 % proc c {a b} {concat $a $b}
() 70 % ::tcl::unsupported::disassemble proc c
ByteCode 0x00000000045A2660, refCt 1, epoch 16, interp 0x0000000002E26120 (epoch 16)
Source "concat $a $b"
Cmds 1, src 12, inst 10, litObjs 0, aux 0, stkDepth 2, code/src 0.00
Proc 0x0000000002EB32A0, refCt 1, args 2, compiled locals 2
slot 0, scalar, arg, "a"
slot 1, scalar, arg, "b"
Commands 1:
1: pc 0-8, src 0-11
Command 1: "concat $a $b"
(0) loadScalar1 %v0 # var "a"
(2) loadScalar1 %v1 # var "b"
(4) concatStk 2
(9) done
该字节码(底部的四行)由Tcl解释器内部的虚拟机执行。 当前是基于堆栈的VM。 您可以在generic/tclExecute.c
文件中找到其实现。
并非所有命令都可以字节Tcl_*ObjCmd
,如果命令没有匹配的字节码,则会生成对普通函数的调用,例如,提到的直接执行Tcl_*ObjCmd
之一。
在大多数情况下(几乎在每次重用命令时)字节码都快得多。 这是建议将所有代码放入过程(它们以这种方式进行字节编译)并支撑表达式的原因之一。
希望这能说明这一过程。 我遗漏了一些更复杂的细节,例如编译时代以及协同例程,非递归引擎等问题。
对此,Expect与普通的Tcl相同,它只是通过Tcl_CreateObjCmd()
添加了一些额外的命令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.