运行tcl脚本时的后台进程是什么?

时间:2015-04-16 11:05:55

标签: tcl

当你启动一个tcl脚本时,会发生什么后台进程。 (类似于c编译)?

当您开始期望时,脚本过程如何工作?

1 个答案:

答案 0 :(得分:1)

假设您已经有一个正在运行的Tcl解释器并且只运行了source脚本(这避免了描述整个解释器启动序列和初始化),那么在最近的(8.x)Tcl解释器中会发生以下情况:

这基本上调用了一些像Tcl_EvalFile()这样的C代码,它将脚本加载到内存中,并将实际执行的工作交给内部TclEvalEx(),这是{{{}}的私有版本。 1}},如此处所述(https://www.tcl.tk/man/tcl/TclLib/Eval.htm)。

这解释了没有字节码编译的顶级脚本,例如解析脚本,一旦找到命令,就直接执行。这是非常缓慢的,旧的Tcl 7.x一直在运行。

但是如果执行命令,则检查命令是否可以字节编译为更有效的形式。这是通过Tcl_EvalEx()定义的命令的情况,因此如果第一次执行命令,proc会在内部调用Tcl_EvalObjEx()以获取命令的字节码表示,该命令缓存在已解析命令的TclCompileObj()

如果命令无法编译,则直接执行,例如调用Tcl_Obj中的一个函数,例如,处理命令generic/tclCmd*.cconcat中的命令为Tcl_ConcatObjCmd()。此函数也可能来自加载到解释器中的某个C扩展,并且以完全相同的方式处理。可用命令在内部注册在某个哈希表中,这就是generic/tclCmdAH.c所做的事情。

但是如果可以编译命令,就会发生不同的事情。在这种情况下,命令变为字节码表示。例如,对于这样一个简单的过程:Tcl_CreateObjCmd()这将变成四个字节码。您实际上可以通过proc c {a b} {concat $a $b}命令检查生成的字节码,看看这个Tkcon会话和Tcl 8.6.3:

::tcl::unsupported::disassemble

此字节码(底部的四行)由Tcl解释器内的虚拟机执行。它目前是基于堆栈的VM。您可以在() 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 文件中找到它的实现。

并非所有命令都可以进行字节编码,如果命令没有匹配的字节码,则生成对普通函数的调用,例如,提到直接执行的generic/tclExecute.c事之一。

对于大多数情况,字节码更快(几乎每次重复使用命令时)。这是建议将所有代码放在过程中的一个原因(它们以这种方式进行字节编译),并支持你的表达式。

希望这能说明一下这个过程。我遗漏了一些更复杂的细节,如编译epoches和协同例程的问题,非递归引擎等。

Expect与普通的Tcl完全相同,它只是通过Tcl_*ObjCmd添加了一些额外的命令。