http://ja.doukaku.org/127/
指定コマンドを別プロセスで起動
を考えてみました。
以前の投稿
http://inferno-hell.blogspot.com/2009/03/blog-post.html
をベースにしてみました。
パイプでのやり取りが難しく、結局C言語(posix)っぽくなりました。
明示的にパイプをクローズするのが簡単にはできないようではまりました。
以下コードです。
インデントがうまくいかなく、みづらいので、
気になる方はどう書く.orgの方の参照お願いします。
http://ja.doukaku.org/comment/8800/
implement d127;
include "sys.m";
sys: Sys;
include "draw.m";
include "sh.m";
sh: Sh;
d127: module{
init: fn(ctx: ref Draw->Context, argv: list of string);
};
init (ctx: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
sh = load Sh Sh->PATH;
buf := array[64] of byte;
fds := array[2] of ref Sys->FD;
argv = tl argv;
if(argv == nil){
return;
}
cmd := hd argv;
sys->pipe(fds); # open pipes
spawn child(ctx, fds[0], cmd);
# Read results of child process
n: int;
fds[0] = nil;
fdd := sys->open("/dev/cons", sys->OWRITE);
for(;;){
n = sys->read(fds[1], buf, len buf);
if(n == 0){
break;
}
# print result
sys->fprint(fdd, "%s", string buf[0:n]);
}
}
child (ctx: ref Draw->Context, fd: ref Sys->FD, cmd: string)
{
# duplicate stdout to the pipe
sys->dup(fd.fd, 1);
sh->system(ctx, cmd);
# pipe close
fdn := sys->open("/dev/null", sys->OWRITE);
sys->dup(fdn.fd, 1);
fd = nil;
}
ポイントはパイプをオープンして片方を子プロセスに渡すということと、
処理終了後になんとかパイプをクローズしているところです。
ファイルやパイプをクローズするにはcloseというシステムコールはなく、
どこからも参照しなくならないようにしなければなりません。
なので、三カ所で無理矢理パイプの参照を切っています。
1. 親プロセスの中、子プロセス呼び出し後、ファイルデスクリプタにnil代入
2. 子プロセスで、stdoutをパイプではなく、/dev/nullに
3. 子プロセスで、ファイルデスクリプタにnil代入
0 件のコメント:
コメントを投稿