模拟 execvp - 有更好的方法吗?
我目前正在用 Tcl/Tk 包装一个命令行工具(espeak
),到目前为止我已经弄清楚了:
load ./extensions/system.so
package require Tk
package require Tclx
set chid 0
proc kill {id} {
exec kill -9 $id
}
proc speak {} {
global chid
set chid [fork]
if {$chid == 0} {
execvp espeak [.text get 1.0 end]
}
}
proc silent {} {
global chid
kill $chid
}
其中 system.so 是我一起破解的扩展,以便能够使用 execvp
:
#include <tcl.h>
#include <tclExtend.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static int
execvp_command(ClientData cdata, Tcl_Interp *interp, int argc, const char* argv[])
{
if (argc == 1)
{
interp->result = "execvp command ?args ...?";
return TCL_ERROR;
}
execvp(argv[1], argv + 1);
return TCL_OK;
}
int System_Init(Tcl_Interp* interp)
{
if (Tcl_InitStubs(interp, "8.1", 0) == NULL)
return TCL_ERROR;
Tcl_CreateCommand(interp, "execvp", execvp_command, NULL, NULL);
Tcl_PkgProvide(interp, "system", "1.0");
return TCL_OK;
}
我需要 execvp
的原因是因为由 exec
(Tcl) 创建的子进程似乎在进程终止时继续运行(我可以通过以下方式确认这一点) ^C
'ing out of the GUI),而如果我使用 execvp
,espeak
会正常终止。
因此,我从这个脚本中真正需要的是能够启动一个子进程并根据需要终止它。
是否有另一个库可以正确执行此操作,例如 Expect?
I'm currently wrapping a command line tool (espeak
) with Tcl/Tk, and I have figured this out so far:
load ./extensions/system.so
package require Tk
package require Tclx
set chid 0
proc kill {id} {
exec kill -9 $id
}
proc speak {} {
global chid
set chid [fork]
if {$chid == 0} {
execvp espeak [.text get 1.0 end]
}
}
proc silent {} {
global chid
kill $chid
}
Where system.so is an extension I hacked together to be able to use execvp
:
#include <tcl.h>
#include <tclExtend.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static int
execvp_command(ClientData cdata, Tcl_Interp *interp, int argc, const char* argv[])
{
if (argc == 1)
{
interp->result = "execvp command ?args ...?";
return TCL_ERROR;
}
execvp(argv[1], argv + 1);
return TCL_OK;
}
int System_Init(Tcl_Interp* interp)
{
if (Tcl_InitStubs(interp, "8.1", 0) == NULL)
return TCL_ERROR;
Tcl_CreateCommand(interp, "execvp", execvp_command, NULL, NULL);
Tcl_PkgProvide(interp, "system", "1.0");
return TCL_OK;
}
The reason I need execvp
is because a subprocess created by exec
(Tcl) seems to keep going when the process dies (I can confirm this by ^C
'ing out of the GUI), whereas if I use execvp
, espeak
dies properly.
Thus, all I really need out of this script is to be able to start a subprocess and kill it on demand.
Is there another library that can do this properly, like Expect?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Tcl 在内部使用
execvp
(确实;我刚刚检查了源代码),因此差异在于其他地方。其他地方将出现在信号中;由 exec 命令创建的子进程(以及使用相同底层引擎的其他事物)将强制大多数信号使用默认信号处理程序,但由于它设置为非默认信号的唯一信号是 SIGPIPE,我想知道还发生了什么。也就是说,处理此类事情的最终扩展是 TclX。这使您可以访问您一直在部分使用的所有低级 POSIX 功能。 (期望也能做到。)
Tcl uses
execvp
internally (really; I've just checked the source) so the difference lies elsewhere. That elsewhere will be in signals; the subprocess created by theexec
command (and other things that use the same underlying engine) will have the majority of signals forced to use the default signal handlers, but since the only signal it sets to non-default is SIGPIPE, I wonder what else is going on.That said, the definitive extension for working with this sort of thing is TclX. That gives you access to all the low-level POSIX functionality that you've been using partially. (Expect may also be able to do it.)