連載 / , / Li 社 Language + > {bottom fi11x} {frame + > {left fillx expand padx 5 pady 5 } \ inx {label —text 0 -width 5 \ + > {left fillx expand padx 5 pady 5 } \ {label -text "total: " } run {label —text 0 -borderwidth 1 -width 8 } —borderwidth 3 —relief sunken} # パネル上の部品を初期化 } ] {top fillx filly expand}; {button —text 再生—command do_play} + > {left fillx expand} play\ {button —text コマ送り—command do_step} + > {left fillx expand} step\ {button —text 停止—command do_stop} + > {left fillx expand} stop\ $WTE1ements (curr) configure —text EMPTY if {$inx==O} then { } else { if {$curr= ー 1 } then { $WTE1ements (curr) configure } else { $WTE1ements (curr) configure —text INIT; —text $curr ; if {$inx==0} then { $WTE1ements (inx) configure } else { $WTE1ements (inx) configure —text EMPTY —text [expr $inx—l] ; $WTE1ements (run) configure —text $run # ユーティリティ・ルーチン proc do—stop { } { global run ; g10ba1 WTE1ements ; set run stop $WTE1ements (run) configure proc do-step { } { global inx curr scene ; global WTE1ements ; —text $run ・ if {$inx = = 0 } then {return} ; xncr CUrr ; if {$curr く $inx} then { eval [concat $WTE1ements(viewer) $scene($curr)] ; 82 UNIX MAGAZINE 1993.10
連載 / Li 眈 Language $Te (c) bind dot く Any-Leave> "$Te (c) itemconfig current -fill SkyB1ue2" $Te(c) bind dot く ButtonRe1ease—1> "$Te(c) dtag selected" $Te(c) bind d0t く 1 > "d0tDown $Te(c) %x %y" bind $Te(c) # 大域変数 く B1-Motion> "dotMove $Te (c) %x %y" set dot (1astX) 0 set dot (1astY) 0 # マウスポタンが押されたときの処理 proc d0tDown {w x y} { global dot $w dtag selected $w addtag selected withtag current $W raise current set d0t(IastX) $x set d0t(1astY) $y # マウスポタンが押されながらドラッグされたときの処理 proc d0tMove {w x y} { global dot $w move selected [expr $x—$d0t(1astX)] [expr $y-$dot (1astY)] set dot (IastX) $x set dot(1astY) $y # 終了処理 EndRecordCanvas を呼び出して、記録ファイルをクローズしている proc do—end { } { g10baI Te ; EndRecordCanvas $Te (c) ; destroy リスト 11 RecordCanvas て記録された情報を再生するアプリケー # ロードバスの設定 lappend auto-path # 大域変数の設定 ション set set set set 80 inx 0 ; curr ー 1 ; run stop ; interval 50 ; UNIX MAGAZINE 1993 ユ 0
前述のファイルをコピーして保存する方法では、バー ジョンを取り出すときにファイル名とバージョンの対 応を管理する機能や変更の記録をとる機能がなく、複 数の人間が扱う場合にロック機構が必要になると説明 しました。バージョン管理システムを用いるもう 1 つ の大きな理由に、バージョンを保存するためのディス ク容量の間題があります。 ファイルをコピーする方法では、それぞれのバージョ ンをすべてそのまま保存するので、かなりのディスク容 量を消費してしまいます。しかレヾージョン管理システ ムを用いると、通常は直前のバージョンとの差分だけが 保存されます。プログラムを変更するときには、全体で はなく局所的な変更をおこなうことが多く、変更部分の 差分はファイル全体と上交するとかなり小さくなりま す。筆者の使っている環境はディスクをふんだんに使 えるものではないので、ディスク容量の節約のためだ けにユーザーに RCS の使用をお願いしています。 / 、一ジョンツリ 実際の使い方の前に、もうすこし RCS について説明 しておきましよう。バージョンは直前のバージョンとの 差分として保存されると書きましたが、 1 つのバージョ ンから複数の異なるバージョンを作成することも考え られます。たとえば、ある段階でリリースしたバージョ ンをそのあとも改良のために編集していたところ、リ リースしたものにバグが発見されたとしましよう。こ の場合にはリリースしたバージョンに潜んでいるバグ を修正するために、そのバージョンを元に新たなバー ジョンを作成することになります。すると、リリース したバージョンからは、開発の流れに沿ってできたバー ジョンとノヾグフィックスのためのノヾージョンという 2 つ か作られます。 RCS ではこのような状況に対応するために、すべて のバージョンはバージョンツリーと呼ばれる : イ冓造のか たちで保存されています。この料冓造の根にあたるのが 最初に作成したバージョンです。それぞれのバージョン を指定するには、バージョン番号を用います。この番号 は、 2n 個の ( ドットで区切られた ) 数字です。最初の バージョンには、 1.1 というバージョン番号が与えられ ます。バージョン 1.1 を編集して新たにバージョンを 150 図 1 ′く一ションツリ 1.2 1 2 1.2.1.1 1.1 1.2 1.2.2.1 2.2 2.1.1.1 2.1 作成すると、後ろの数字が 1 増やされてバージョン 1.2 となります。このまま 1.3 、 1.4 、 と続けていくこ ともできますが、数字 2 個からなっているバージョン は先頭の数字を増やすこともできます。たとえは、次の バージョンを 2.1 などとできるのです。バージョン 2.1 の次は、後ろの数字を 1 増やしたバージョン 2.2 にな ります。 2n 個の数字と書きましたが、これは 1 つのバージョ ンから新しいバージョンを複数作成したときに現れま す。たとえはさきはどの続きで、バージョン 1.2 から もう 1 つ新しいバージョンを作成したとしましよう。 こで作成されたバージョンには、 1.2.1.1 というバー ジョン番号が与えられます。この番号は、 1.2 という バージョン ( 1.2.1.1 ) から出ている 1 本目の ( 1.2 ュ .1 ) 枝分かれの、 1 つ目の ( 1.2.1.1 ) バージョンという意味 になります。このバージョンからさらに次のバージョン を作ると、最後の数字を 1 増やした 1.2.1.2 というバー ジョンになります。 こでノヾージョン 1.2 から、もう 1 つ新しいノヾージョ ンを作ることを考えてみましよう。今度は、 1.2 という バージョンから出ている 2 本目の枝分かれの 1 つ目の バージョンになるので、バージョン番号は 1.2.2.1 と なります。このように、続けて開発していくときは ( と くに指定がなけれは ) 最後の数字を 1 っ増やしたもの、 枝分かれさせるときは元となるバージョン番号に何本 目の枝かを示す数字と 1 を付けたものカ噺しく作成さ れるバージョン番号となります ( 図 1 ) 。 数字が 2 個のバージョンは、先頭の数字を大きくで きるという特別な扱いをしました。このようなバージョ ンは開発の主役であるバージョンの流れで、数字が 4 個 UNIX MAGAZINE 1993.10
連載 / BSD / 386 ー⑨ 図 4 ビデオポードの尺 r Sigma Legend Paradise 1024 p Paradise Professiona1 0 GENOA 6400 Ⅱ GENOA 5300 / 5400 m Tseng et4000 UN ー 4010 STB Powergraph IM Orchid Prodesigner lls Orchid Prodesigner II 1 EIZO VA41 IM h Diamond Speedstar + HiC01 g Diamond Speedstar + IM Diamond Speedstar II + Diamond Speedstar HIcoIor d CompuAdd HiRez IM Cardina1 et4000 IM b BOCA Research with IM a 2—the—MAX VGA 4000 q 1 k J f e c s TVGA 8900C t*ATI U1tra A Paradise 8514 z Pixe1Works Whir1Win y Nth Engine/150 x Orchid F1280 GENOA 8514 v ELSA Winner u Diamond Stea1th X display adapter selection Se1ect a display adapter type, press Q when done 図 5 マウスの尺 ATI Bui1t—In Busmouse Microsoft Busmouse MM series Logitech Mouseman b Logitech FirstMouse a Logitech (standard, C7) f e d c g Microsoft Seria1 x mouse selection *=selected, letter toggles Se1ect a mouse type, 図 6 マウスとシリアルポートの対応 a /dev/ttyOO b /dev/tty01 c /dev/tty02 press Q when done *=selected, letter toggles X mouse port selection Se1ect a mouse port type , press Q when done にリターンを入力すると xconfig か作らインストー ルは終了する。 こで問題になるのは、使っているビデオポードやディ スプレイがリストにない場合である。 リストにないディスプレイ 使っているディスプレイがリストになかった場合は、デ イスプレイ・タイプを指定するときに 0t er のエントリ を選ぶ。画面か図 8 のように変わるので、ディスプレイの 48 *=selected, letter toggles 水平同期周波数、ピデオポードのクロック、利用する X サーバーの解像度を入力すれは、 xconfig が作成できる。 リストにないビデオポード ビデオポードの場合も、リストにないものを追加するだ けでよい。 configx コマンドか利用している各種の情報は、 /usr/ libdata/configx ・ data というテキストファイノレに言己 述されている ( 図 9 ) 。 UNIX MAGAZINE 1993 ユ 0
AThe 1993 Solaris Developer Conference 図に OLTP でのマルチスレッドの利用例 ( a ) スレッドが一つしかない場合 ( b ) マルチスレッド化した場合 fO 「 Server 1 User Kernel Network Server1 日 u t fO 「 Server 2 Server2 se Ⅳ 1 の実行カるまで s 2 への要求は出せない。 User fo 「 server 1 fO 「 Server 2 Thread 1 Thread 2 Thread 3 Kernel Network Server2 Server1 server 1 の終了を待たずに s er 2 への要求が発行できる。 sew 1 への要求を おこなったスレッド ( 1 e 記 3 ) は、 se Ⅳ 1 から応答があった段階で処理を再開 する。 の後半にも発売されるとのことです。 OLTP の分野では、 1 つのクライアントが複数のサ ーに同時に問合せをおこない、その結果を得てから 処理を進めていきます。これを単一のスレッドでおこな った場合、 1 つのサーバーへの問合せを発行すると、そ の返事力唳ってくるまで次のサーバーへの問合せがで きません。 MT を使って、問合せをおこなうスレッドを 各サーバーごとに 1 っすっ生成すると、サーバーの応答 を待たすに、別のサーバーへの問合せを発行することが できます ( 図 12 ) 。この例のような場合なら、マルチプロ セッサでないマシンでもスルーブットの向上か望めます。 OLTP によく似た応用例としては、 X ウインドウ・サ ーバーの MT 化が考えられます。 X のサーバーは、複数 のクライアントからの入出力要求を並列的に処理しなけ ればなりません。ここで、クライアントごとに窓口とな るスレッドを 1 っすっ割り当てれば、パフォーマンスの 向上はもちろん、サーバーのコードの単純化も可能で す。 X の次のバージョン X11R6 では、サーバーやクライ アントに MT を利用する計画もあるようです。 以上の例はいすれも、複数のプロセスや LWP を利用 する方法でも実現できますが、プロセス生成やコンテキ スト・スイッチのオーバーヘッド、プロセス数の制限な どを受けるため、実用性には欠けてしまいます。 18 MT への対応 SoIaris 2 . 2 では、カーネルレベルにおいては MT に 対応していますが、標準ライプラリの一部は MT での 利用に制限があります。この制限をなくしたライプラリ が、近日中にリリースされる予定です。また、 MT 対応 のデバッガ、 Ada 、 Fortran などが 1993 年中にリリー スされるそうです。 Solaris Developer Conference は、その名のとおり アプリケーション開発者などを対象にしており、セッシ ョンの内容はかなり専門的で多岐にわたっています。し たがって、とてもすべてを紹介することはできません。 しかし、いすれのセッションでもキーワードとなってい たのが、「 Distribution. 」と「 Enterprise Use 」です。 前回も触れましたが、 SunSoft は SoIaris のターゲット をかなり大規模なネットワークをもつ企業ューザーに 絞っているようです。 lntel 版 Solaris についても、個人 のアプリケーション・ユーサーより、高性能サーバーを 中心とした中・大規模ネットワークのクライアントとし て位置づけています。 UNIX MAGAZINE 1993.10
連載 / / Li 眈 Language path C01 tree array # 戻り値 生成される行列ウィジェットの名前 . 行の名前と繰返し回数 . 列の名前と繰返し回数 WidgetTree に渡すものと同様の仕様 生成されたウィジェット群すべての名前を保持している配列 # 生成された行列ウィジェットのパス ( すなわち path そのもの ) proc Matrix {path ro C01 tree {an WTE1ements}} { upvar $an elem ; set here Cexpr [inf0 level] ー 1 ] , return [-Matrix— $path $row $ C01 $tree $here elem] ; frame $path ; upvar $an elem; proc —Matrix— {path row C01 tree level an} { set set set set for ri [lindex $ ro 0 ] ; upvar #$level $ri r 1 ] ; 0 ] ; upvar #$level $ci c 1 ] ; cn [lindex $ C01 ci [lindex $ C01 rn [lindex $row {set r 1 } {$r く = $rn} {incr r} { {left fillx expand}; [-WidgetTree- $path. $ri$r. $ci$c $tree $level elem] \ pack append $path. $ri$r \ for {set c 1 } {$c く = $cn} {incr c} { {top fill expand} ; pack append $path [-WidgetTree— $path. $ri$r {frame} $level elem] \ return $path ; リスト 15 RecordCanvas 、 EndRecordCanvas # RecordCanvas by srekcah@sra ・ CO ・ JP RecordCanvas は指定された canvas に対しておこなわれるすべての操作を 指定されたファイルに書き出します # 使い方 : RecordCanvas canvas [file] 引数 C anvas file 戻り値 なし 記録したい canvas のパス名を指定 記録を保存するファイル名を指定 デフォルトは "canvas ・ 10g" proc RecordCanvas {canvas {file canvas. 10g } } { global CanvasRecorderPrivate ; if [infO exists CanvasRecorderPrivate ($canvas) ] then { close $CanvasRecorderPrivate ($canvas) ; unset CanvasRecorderPrivate ($canvas) ; UNIX MAGAZINE 1993 ユ 0 85
連載 /An lntroduction to X Window System 一番号名前 表ー xgraph のオプション オプション指定 =WxH + X + Y -bw 幅 -bd 色 -bg 色 -fg 色 —t タイトル -x 単位名 -y 単位名 -ly 最小値 , 最大値 -lx 最小値 , 最大値 フォント名 フォント名 ¯P —nl -gs 形式 -lv 幅 -zv 幅 -zg 色 —tk —bb -lny —lnx —lf —t f —brw 幅 -brb 基準値 —bar オプション名 Geometry Tit1eText XUnitText WnitText ( データ中では " 名前 " で指定 ) Tit1eFont Labe1Font XLowLimit , XHighLimit YLowLimit ,YHighLimit LogX LogY BoundBox Ticks GridSize ZeroC010r ZeroWidth LineWidth GridSty1e BorderSize Border Background Foreground ReverseVideo Debug NoLines Marker s St yl eMarkers Pixe1Markers LargePixe1s BarGraph BarBase BarWidth 番号 . C 。 1 。 r 番号 . Sty1e ZeroSty1e Device Disposition Fi1eOrDev UNIX MAGAZINE 1993.10 xgraph の大きさと位置 ( X11R3 当時の表記であること Y 軸の単位を示す名前 ( 省略時は Y) X 軸の単位を示す名前 ( 省略時は X) グラフ上部のタイトル名 ( 省略時は X Graph) 作 (xgraph のデバッグ用 ) オプションの指定値を表示するとともに同期モードで動 白黒反転 ウインドウの表示色 ウインドウの背景色 ウインドウの枠色 ウインドウの枠幅 に注意 ) 159 のコマンドのオプション、またはファイル名 ) 省略時のハードコピーの出力先の名前 ( プリンタ名など ァイル ) 省略時の出力先 ()o Device= プリンタ、 To Fi1e= フ ードコピー出力時の省略値 ン 座標軸の線種の指定形式は 0 と 1 からなるピットパター ピットパターン ( 番号は 0 ~ 7 ) 各データに対する線種の指定。形式は 0 と 1 からなる 各データに対する色の指定 ( 番号は 0 ~ 7 ) 棒グラフの幅の指定 ( 単位 : X 軸の値。省略時は lpixel) 棒グラフの基準値を指定 ( 省略時は 0 ) で棒グラフを作成 -brb オプションで指定される基準値から -brw の幅の線 小 データの座標位置がはっきり分かるような大きな点を表 データの座標位置に小さな点を表示 ( 分布図などに使用 ) データの座標位置に点を表示 連続する 8 つのデータ群で、同しマークになるように データの座標位置に点を表示 ときに指定 ) 折れ線を描かない ( 棒グラフ、点だけのグラフにしたい ピットパターン ) 座標軸以外の方眼線のパターン ( 形式は 0 と 1 からなる 折れ線グラフの線幅 ( 単位 : pixel) 座標軸の幅 座標軸の色 座標軸以外の方眼線の幅 ( 単位 : pixel) 方眼表示ではなく、グラフの外周に短い線で値を示す グラフ全体を罫線で囲む Y 軸を対数表示 X 軸を対数表示 Y 軸の表小領域の設定 X 軸の表示領域の設定 軸や値表示に用いるフォント タイトル表示に用いるフォント 凡例で用いるデータの名前 ( 番号は 0 ~ 63 の整数 )
一の 1670 万レガ一ーで 1 ノヂ大画面一 , , 訟下電器狂コンピ蔘タシズム
連載 / コアダンプするんですけどー 3 return 1p ; int wni—closelog(lp) log—t *lp ; if ()p = = NULL) return ー 1 ; UNIX MAGAZINE 1993 ユ 0 fclose(lp—>logfp) ; lp—>modeflags ー = LG—DISABLE; return ー 1 ; if (lp—>modeflags & LG_DISABLE) return ー 1 ; if ()p = = NULL) log-t *lp ; int vni—disablelog (lp) return newmode ; lp—>modeflags = newmode , return ー 1 ; if ()p = = NULL) unslgned 10 Ⅱ g newmode ; log—t *lp ; int wni—logmode ()p , newmode) return lp—>limitsize; lp—>maxfilenum = newsize ; return ー 1 ; if ()p = = NULL) unsigned long newsize ; log—t *lp ; int wni-logfiles(lp, newsize) return lp—>limitsize ; lp—>limitsize = newslze; return ー 1 ; if ()p = = NULL) 10 Ⅱ g newsize ; log—t *lp ; int wni—logsize ()p , newsize) return 0 ; free(lp) ; free (lp—>filename) ; fclose(lp—>logfp) ; fflush(lp—>logfp) ; if ( (lp->modeflags & LG_DISABLE) = の { 145
連載 / Li 眈 Language 図 2 ばたん 1 ばたん 2 ばたん 3 図 3 カウンタ 囹 t. 凹 0 WidgetTree の進んだ使い方 ここでは tree の扣疋方法と、 array の使い方について 詳しく解説します。 前述の説明では、 tree 窈旨定は単純に構造を書き下して いくだけでしたが、あとになってプログラム中で材冓造の なかの部品を参照したくなることがあります。このような 場合は、 tree の定義中で日月カ郊勺に部品の名前を指定できま す。名前は pack のパラメータと子ウィジェットの定義の リスト 2 が使用例です。このとき画面は図 2 のようにな ります。 WidgetTree は引数の path 名を返すので、 pack の引数の一として使うことかできるのです。 親として指定できるのは、 pack の親となることができ るウィジェットです。すなわち、いまのところ許されてい るのは、 frame と toplevel ということになります。リス ト 3 のように定義す川ま、新しい toplevel ウインドウ上 に WidgetTree を使ったウィジェットを定義できます。 この WidgetTree を用いてリスト 1 を書き換えてみま しよう。その結果をリスト 4 に示します ( 結果はもちろ ん図 1 と同じです ) 。よけいなウィジェット名か消え、構 造もすっきりしてより見やすくなったと思いませんか ? { 親 widget あいだに指定します。 + > pack の /ヾラメータ名前 { 子 widget} + > pack の′ヾラメータ名前 { 子 widget} + > pack の′ヾラメータ名前 { 子 widget} UNIX MAGAZINE 1993 ユ 0 はデフォルトで WTEIemets という酉咀ゴ内されてい 値が 1 すっ増えていくようにします。ウィジェットの名前 いうボタンを押すと、真ん中のラベルに表示されている数 ます。この画面に、処理を定義してみましよう。、、十 1 " と ルに disp という名前を付けています。画面を図 3 に示し 具体例をリスト 5 に示します。ここでは 2 番目のラベ て、次のようにアクセスできます。 WTE1ements (disp) 当然ですが、 foreach a [array names WTE1ements] { puts stdout "WTE1ements ($a) =$WTE1ements ($a) " とすれは、 WTElements の内容を見ることができます ( 誌面の都合上で折り返しています ) 。 ボタンを押すたびに表示が 1 すっ増えていく処理を追 加したものを、リスト 6 に示します。すでにお気づきの ことと思いますが、 tree の定義中て参照する変数名は、す べて、、 WidgetTree を呼び出したレベルのコンテキスト " で解釈されます。すなわち、この例では最当立から直接 WidgetTree を呼び出しているので、 tree のなかでの変 数の参照はすべて最日立レベルて解釈されます。 —command {incr $WTE1ements (disp) configure —text $counter} この処理は、 disp て指定されるウイジェットに counter の値を設定することを示しています。 系区しになりますが、 WidgetThee の第 3 引数に配列 名を与えると、 WTEIements の代わりにその酉冽カイ吏用 されます。 Matrix ユーティリティ WidgetTree によって、上交的単純な哥冓造は指定し やすくなりました。次に紹介するのは、これと組み合わせ て使える Matrix というユーティリティです。これは名 前から想像できるように、指定されたウィジェットを 2 次 元に配置します。任意の WidgetTree か配置できるので、 いくらでも複雑な画面を作成できます。外部イ策は以下の とおりです。 形式 Matrix path て ow C01 tree [array] 引数 path C01 tree 生成される行列ウィジェットの名前 行の名前と区し回数 列の名前と区し回数 WidgetTree に渡すものと同様の 73