ソース探検 > 01

「ソース探検/01」の編集履歴(バックアップ)一覧はこちら

ソース探検/01」(2008/08/27 (水) 10:00:15) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

-先生: --「それでは、今日の宿題はpauseコマンドです。Infernoがはじめてのみなさんにも簡単に読めるソースですので、忘れずにやってきてくださいね。」 -デーモソ君: --「は~い!」 どうやら中学校ではじめての宿題となったのはpauseコマンドのようです。デーモソ君は無事に宿題をこなすことができるでしょうか。 家に帰ったデーモソ君はさっそくノートPCを開きました。 -デーモソ君: --「まずはソースがどこにあるかだよね。manページに書いてあるかな?えいっ」 #blockquote(){; man pause SLEEP(1) NAME sleep, pause - suspend execution for an interval SYNOPSIS sleep n pause DESCRIPTION Sleep suspends its own execution for n seconds before returning. Pause never returns, and is typically used to stop a command interpreter reading any more from the standard input. SOURCE /appl/cmd/sleep.b /appl/cmd/pause.b SEE ALSO sys-sleep(2) Inferno Manual } デーモソ君の狙いどおり、SOURCEセクションにソースの場所が書かれていました。デーモソ君はつづけてソースを開きます。 #aa(){{{implement Pause; # # init program to do nothing but pause # include "sys.m"; include "draw.m"; Pause: module { init: fn(nil: ref Draw->Context, nil: list of string); }; init(nil: ref Draw->Context, nil: list of string) { <-chan of int; } }}} -デーモソ君: --「うわっ、見たことない言語で書かれてるよ!えーん、えーん、パパー!」 -パパ: --「どうしたんだ?デソ。」 -デーモソ君: --「Infernoは、C言語じゃないんだ!」 -パパ: --「そりゃそうだ。Cは小学校までだ。これからはLimboだよ。」 -デーモソ君: --「Limbo?」 -パパ: --「そう。Infernoはそれ自体はCで書かれているけど、Inferno上で動くアプリケーションはLimboで書かれてる。分散アプリケーションを書くのに優れた言語だよ。」 -デーモソ君: --「そうなんだ。C言語とはどう違うの?」 -パパ: --「それは簡単には説明できないな。ちゃんとマニュアル&footnote(http://www.vitanuova.com/inferno/papers/descent.html)があるんだから読んでごらん。で、宿題は…pauseコマンドか。initがCのmainみたいなものだから、とりあえずそこから読んでみるといい。」 デーモソ君はあらためてinit関数を見てみました。 #aa(){{init(nil: ref Draw->Context, nil: list of string) { <-chan of int; } }} -デーモソ君: --「ここだけみても、やっぱりよくわからないんだ。どうして「<-chan of int;」だけでプロセスがブロックするの?」 -パパ: --「まず、"<-"はチャネルオペレータだね。Infernoはチャネルという機構でプロセス間通信を実現してるんだよ。Unixでいうパイプやソケットみたいなものだね。でもここでは送信元も送信先も明示していないね。」 -デーモソ君: --「そんな記述ができるんだ。でもこれだけじゃやっぱり何をやっているのかわかんないや。」 -パパ: --「『目に見えるものだけが真実ではない』と偉い人は言ってるだろう。Limboのソースだけでわからなければダンプしてみればいい。」 そう言ってパパはpause.disをダンプして見せてくれました。 #blockquote(){{; disdump /dis/pause.dis newcw , $0, 44(fp) recv 44(fp), 40(fp) movp 0(mp), 44(fp) ret ; }} -デーモソ君: --「あのソースがたったこれだけなんだ。」 -パパ: --「これはInfernoの仮想マシンの命令だから、命令の意味はDisのマニュアル&footnote(Dis Virtual Machine Specification http://www.vitanuova.com/inferno/papers/dis.html)を見てごらん。」 デーモソ君は各命令の意味を調べました。 #blockquote(){{newcx - Allocate channel Syntax: newcw dst newcb dst newcl dst newcf dst newcp dst newcm src, dst newcmp src, dst Function: dst = new(Channel) The newc instruction allocates a new channel of the specified type and stores a reference to the channel in dst. For the newcm instruction the source specifies the number of bytes of memory used by values sent on the channel (see the movm instruction above). For the newcmp instruction the first operand specifies a type descriptor giving the length of the structure and the location of pointers within the structure (see the movmp instruction above). }} #blockquote(){{recv - Receive from channel Syntax: recv src, dst Function: dst = <-src The recv instruction receives a value from some other thread on the channel specified by the src operand. Communication is synchronous, so the calling thread will block until a corresponding send or alt is performed on the channel. The type of the received value is determined by the channel type and the dst operand specifies where to place the received value. }} #blockquote(){{movp - Move pointer Syntax: movp src, dst Function: destroy(dst) dst = src incref(src) The movp instruction copies a pointer adjusting the reference counts to reflect the new pointers. }} -デーモソ君: --「newcwはチャネルの生成、recvはチャネルからの受信、movpはポインタのコピーだね。」 -パパ: --「それだけ分かれば十分だ。大事なのは、チャネルの受信側はInfernoのスケジューラによって待ち状態にされる。次に実行状態になるのはチャネルから受信があった時、という事だ。」 パパはInferno上のプロセスの状態遷移図を描いてくれました。 -パパ: --「でもpauseコマンドの場合は、チャネルの送信側のプロセスもpauseコマンド自身だ。すでに待ち状態になってるプロセスがチャネルへデータの送信なんて出来ない。」 -デーモソ君: --「そうか。pauseコマンドは来るはずのないデータをずっと待ってる状態なんだね。」 -パパ: --「そのとおり。pauseコマンドはチャネルのしくみをうまく利用した例だな。」 -デーモソ君: --「でも先生は簡単に読めるって言ってたのに、ずいぶん難しかったなぁ。」 -パパ: --「読むことと理解することは違うってことさ。」
-先生: --「それでは、今日の宿題はpauseコマンドです。Infernoがはじめてのみなさんにも簡単に読めるソースですので、忘れずにやってきてくださいね。」 -デーモソ君: --「は~い!」 どうやら中学校ではじめての宿題となったのはpauseコマンドのようです。デーモソ君は無事に宿題をこなすことができるでしょうか。 家に帰ったデーモソ君はさっそくノートPCを開きました。 -デーモソ君: --「まずはソースがどこにあるかだよね。manページに書いてあるかな?えいっ」 #blockquote(){; man pause SLEEP(1) NAME sleep, pause - suspend execution for an interval SYNOPSIS sleep n pause DESCRIPTION Sleep suspends its own execution for n seconds before returning. Pause never returns, and is typically used to stop a command interpreter reading any more from the standard input. SOURCE /appl/cmd/sleep.b /appl/cmd/pause.b SEE ALSO sys-sleep(2) Inferno Manual } デーモソ君の狙いどおり、SOURCEセクションにソースの場所が書かれていました。デーモソ君はつづけてソースを開きます。 #aa(){{{implement Pause; # # init program to do nothing but pause # include "sys.m"; include "draw.m"; Pause: module { init: fn(nil: ref Draw->Context, nil: list of string); }; init(nil: ref Draw->Context, nil: list of string) { <-chan of int; } }}} -デーモソ君: --「うわっ、見たことない言語で書かれてるよ!えーん、えーん、パパー!」 -パパ: --「どうしたんだ?デソ。」 -デーモソ君: --「Infernoは、C言語じゃないんだ!」 -パパ: --「そりゃそうだ。Cは小学校までだ。これからはLimboだよ。」 -デーモソ君: --「Limbo?」 -パパ: --「そう。Infernoはそれ自体はCで書かれているけど、Inferno上で動くアプリケーションはLimboで書かれてる。分散アプリケーションを書くのに優れた言語だよ。」 -デーモソ君: --「そうなんだ。C言語とはどう違うの?」 -パパ: --「それは簡単には説明できないな。ちゃんとマニュアル&footnote(http://www.vitanuova.com/inferno/papers/descent.html)があるんだから読んでごらん。で、宿題は…pauseコマンドか。initがCのmainみたいなものだから、とりあえずそこから読んでみるといい。」 デーモソ君はあらためてinit関数を見てみました。 #aa(){{init(nil: ref Draw->Context, nil: list of string) { <-chan of int; } }} -デーモソ君: --「ここだけみても、やっぱりよくわからないんだ。どうして「<-chan of int;」だけでプロセスがブロックするの?」 -パパ: --「まず、"<-"はチャネルオペレータだね。Infernoはチャネルという機構でプロセス間通信を実現してるんだよ。Unixでいうパイプやソケットみたいなものだね。でもここでは送信元も送信先も明示していないね。」 -デーモソ君: --「そんな記述ができるんだ。でもこれだけじゃやっぱり何をやっているのかわかんないや。」 -パパ: --「『目に見えるものだけが真実ではない』と偉い人は言ってるだろう。Limboのソースだけでわからなければダンプしてみればいい。」 そう言ってパパはpause.disをダンプして見せてくれました。 #blockquote(){{; disdump /dis/pause.dis newcw , $0, 44(fp) recv 44(fp), 40(fp) movp 0(mp), 44(fp) ret ; }} -デーモソ君: --「あのソースがたったこれだけなんだ。」 -パパ: --「これはInfernoの仮想マシンの命令だから、命令の意味はDisのマニュアル&footnote(Dis Virtual Machine Specification http://www.vitanuova.com/inferno/papers/dis.html)を見てごらん。」 デーモソ君は各命令の意味を調べました。 #blockquote(){{newcx - Allocate channel Syntax: newcw dst newcb dst newcl dst newcf dst newcp dst newcm src, dst newcmp src, dst Function: dst = new(Channel) The newc instruction allocates a new channel of the specified type and stores a reference to the channel in dst. For the newcm instruction the source specifies the number of bytes of memory used by values sent on the channel (see the movm instruction above). For the newcmp instruction the first operand specifies a type descriptor giving the length of the structure and the location of pointers within the structure (see the movmp instruction above). }} #blockquote(){{recv - Receive from channel Syntax: recv src, dst Function: dst = <-src The recv instruction receives a value from some other thread on the channel specified by the src operand. Communication is synchronous, so the calling thread will block until a corresponding send or alt is performed on the channel. The type of the received value is determined by the channel type and the dst operand specifies where to place the received value. }} #blockquote(){{movp - Move pointer Syntax: movp src, dst Function: destroy(dst) dst = src incref(src) The movp instruction copies a pointer adjusting the reference counts to reflect the new pointers. }} -デーモソ君: --「newcwはチャネルの生成、recvはチャネルからの受信、movpはポインタのコピーだね。」 -パパ: --「それだけ分かれば十分だ。大事なのは、チャネルの受信側はInfernoのスケジューラによって待ち状態にされる。次に実行状態になるのはチャネルから受信があった時、という事だ。」 パパはInferno上のプロセスの状態遷移図を描いてくれました。 (TODO:図の挿入) -パパ: --「でもpauseコマンドの場合は、チャネルの送信側のプロセスもpauseコマンド自身だ。すでに待ち状態になってるプロセスがチャネルへデータの送信なんて出来ない。」 -デーモソ君: --「そうか。pauseコマンドは来るはずのないデータをずっと待ってる状態なんだね。」 -パパ: --「そのとおり。pauseコマンドはチャネルのしくみをうまく利用した例だな。」 -デーモソ君: --「でも先生は簡単に読めるって言ってたのに、ずいぶん難しかったなぁ。」 -パパ: --「読むことと理解することは違うってことさ。」

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。