For Development HEAD DRAFTSearch (procedure/syntax/module):

6.24 システムインタフェース

GaucheはPOSIX.1の多くの関数と、さまざまなUnixで共通して使われているシステム関数へのインタフェースを 組込み手続きとして提供しています。

多くのScheme実装はいろいろな形で何らかのシステムインタフェースを提供 しています。名前だけが違うもの(例:delete-fileremove-fileunlink) もあれば、新しいSchemeオブジェクトを導入して 抽象化を行っているものもあります。Gaucheでは、既存のAPIのどれかを そのまま真似るのではなく、2つのレイヤを提供することにしました。 この章で述べられる低レベルレイヤは、OSのインタフェースに似せたものを実装します。 その上に、既存のシステムと互換性のある高レベルのインタフェースが実装されます。

sys-nameという名前を持つ手続きは、多くの場合、 システムコールnameに対応しています。 可能な限り、インタフェースが似るようにしました。

なお、システムコールがシグナルによって割り込まれた場合、 そのシステムコールは原則としてリスタートされます。 詳しくはシグナルを参照して下さい。

Cによるシステムプログラミングに慣れている方は、 CとSchemeの関数の対応も参考にして下さい。 Cの標準ライブラリとGaucheの手続きとの対応が示してあります。


6.24.1 プログラムの終了

Gaucheは(mainから返る以外に)自分自身を終了させる方法をいくつか 提供しています。exit手続きが、正しいクリーンアップを行って 優雅に終了する方法です。一方、正しいクリーンアップが不可能な非常事態には sys-exitsys-abortを使います。

Function: exit :optional (code 0) (fmtstr #f) args …

[R7RS+ process-context] 現在のプロセスを終了し、codeを終了コードにします。 code#tなら成功を意味し、終了コードは0に、 code#fなら失敗を意味し、終了コードは1に、 そして正確な整数の場合はその下位8bitが終了コードとして使われます。 codeがそれ以外のオブジェクトの場合は、 終了コードは70 (EX_SOFTWARE)になります。 (R7RSでは、code#tの時正常終了、#fのとき異常終了を示す ということ以外に、具体的にOSレベルのどういった値になるかは規定していません。 ポータブルなコードでは#t#fのみを使うのが良いでしょう。)

fmtstr文字列が与えられた場合、それは残りの引数argsと ともにformatに渡され、standard error portにメッセージとして 印字されます (current-error-portではありません。 ポート共通の操作参照。また、formatについては 出力参照。)

実のところ、プロセス終了の手続きはもう少し複雑です。 正確な段階を次に説明します。

  1. パラメータexit-handlerの値がチェックされます。 もしそれが#fでなければ、それは3引数の手続きとみなされ、 codefmtstr、そして残りの引数のリストを引数として 呼び出されます。実はメッセージを標準エラー出力に出しているのは デフォルトのexit-handlerです。 終了ハンドラの中でエラーが起きた場合、そのエラーは捕捉され捨てられます。 エラー以外の例外は捕捉されません。
  2. アクティブなdynamic-windafterサンクが順に呼び出されます。 afterサンク中で発生した例外は捕捉され捨てられます。
  3. C APIのScm_AddCleanupHandlerで登録されたクリーンアップハンドラが 呼ばれます。このハンドラは通常、Gaucheを内蔵しているアプリケーション特有の クリーンアップをするために使われます。Schemeの世界からはあまり気にする必要は ないでしょう。
  4. まだ閉じられていない出力ポートのバッファが掃き出されます。
  5. exit(3)を呼び、プロセスはcodeから導出される整数値を終了コードとして終了します。

exit-handlerのメカニズムはアプリケーションが終了処理をフックすることを 可能にします。ただし、単純なクリーンアップ処理のためのものではありません (クリーンアップ処理には dynamic-wind, guardあるいはunwind-protectを使う方が 適切です。) exit-handlerはもっと「アプリケーションの終了」という特定の事態に 対して何か処理を行いたい場合に使います。 例えばGUIアプリケーションはメッセージを標準エラー出力ではなく ダイアログとして表示する、というようなことです。

従って、ライブラリコードはexit-handlerに触るべきではありません。 アプリケーションの終了時に何をすべきかを知っているのはアプリケーション自身なのですから。

別の使いどころとしては、サードパーティ製のコードで中でexitが 呼ばれる可能性のあるものを安全に呼び出したいという場合があります。 そのコードを呼び出している間だけ、exit-handlerを エラーではない例外を発生させる手続きへと差し替えます。 エラーではない例外はexitでは捕捉されないので、実質的に 上で説明したような終了処理のステップは中断されることになります (但し、ダイナミックハンドラのafterサンクは通常の例外発生時と 同じように処理されます)。 アプリケーションコードの方でその例外を捕捉してやればよいのです。 parameterizeを使えばexit-handlerを動的に、 かつスレッドセーフに差し替えることが容易になります (パラメータ参照)。

(guard (e [(eq? e 'exit-called) (handle-exit-as-desired)])
  (parameterize ((exit-handler (lambda (c f a) (raise 'exit-called))))
    (call-third-party-library)))

一般的に、他のスレッドが走っている時にexitを呼ぶことは推奨されません。 exit手続きは該当スレッド上でアクティブなダイナミックハンドラしか巻き 戻さないので、他のスレッドはいきなり終了させられてしまいます。 しかしexitを呼ばざるを得ない場合には、 exit-handlerを使って他のスレッドにアプリケーションが終了しつつあることを 伝えられるかもしれません (但しGauche自身は走っているスレッドのリストといった 情報は持っていないので、アプリケーションごとに固有のロジックを実装する必要が あります。)

設計に関する覚書: 終了を一種の例外とすることで、 終了処理を例外処理と統合している言語もあります。 良いアイディアに思えたので我々もそのような実装を試してみましたが、 Gaucheではうまくいきませんでした。大きな理由のひとつは、 dynamic-windの巻き戻し中にafterで例外が 発生すると、その例外がもともとの「終了」例外を隠してしまうことでした。

Parameter: exit-handler

exitが呼ばれた時に呼び出されるexit handlerを保持するパラメータです。 exit handlerは、終了コード、フォーマット文字列、フォーマット文字列の引数のリスト、 の3つの引数を取る手続きです。上のexitの項を参照してください。

exit handlerの値は#fにすることもできます。 その場合はハンドラは呼ばれません。

デフォルトのハンドラは、与えられた引数でフォーマットした文字列を 標準エラー出力に出します。

ハンドラがエラーを投げた場合、それは補足され無視されます。 エラー以外のコンディションを投げた場合は補足されないので、 外側の制御機構に処理が任されます。

Function: sys-exit code

[POSIX] 現在のプロセスを終了し、codeを終了コードにします。 code#tなら終了コードは0、 #fなら終了コードは1、 そして正確な整数の場合は下位8bitが終了コードとして使われます。 それ以外の値では終了コードは70 (EX_SOFTWARE)になります。 (exitと同じです)。

この手続きは_exit(2)を直接コールします。 クリーンアップは一切行われません。 フラッシュされてないファイルバッファの内容は捨てられます。

Function: sys-abort

[POSIX] POSIXのabort()を呼びます。通常、現在のプロセスは終了され、コアダンプされます。 クリーンアップは一切行われません。


6.24.2 コマンドライン引数

Schemeスクリプトに渡されたコマンドライン引数を受け取るには、 main関数の引数を使うのが推奨される方法です (see Schemeスクリプトを書く)。 ただ、簡便のために、どこからでもコマンドライン引数にアクセスできる インターフェースもいくつか用意してあります。

Schemeコードが実行される時、常にコマンドライン引数が存在するわけではない ことに注意してください。例えばアプリケーションに埋め込まれたSchemeコード片にとっては、 コマンドライン引数は意味を持ちません。なるべくmain関数の引数を使うべき、 というのはそのためです。main関数の引数は明示的だからです。 mainが呼ばれたなら、呼び出す側は意識してコマンドライン引数を渡している わけですから。

この注意を念頭に置いておいてください。 以下にコマンドライン引数にアクセスする方法を示します。

Parameter: command-line

[R7RS+ process-context][SRFI-193] 引数なしで呼ばれた場合は、コマンドライン引数のリストを文字列のリストとして返します。 最初の要素はプログラム名です。

Gaucheが埋め込み言語として使われた場合、このパラメータの値はアプリケーションの 設定に依存します。アプリケーションが何もしていなければ、 このパラメータの値は空リストとなります。ライブラリ中でこのパラメータの値を 使う場合は、その可能性を念頭に置いてください。

一つの引数で呼び出すこともできます。その場合、引数は文字列のリストでなければなりません。 渡された引数が、新たなパラメータの値となります。 parameterizeを使ってcommand-lineの値を 動的に変えることができます (パラメータ参照)。 R7RSは、ゼロ引数のcommand-lineのみ定義しています。

Parameter: script-file

[SRFI-193] Schemeプログラムがスクリプトとして実行されている期間中、 このパラメータはそのスクリプトの絶対パスを保持しています。 スクリプトとして実行とは、goshにスクリプトファイルとして渡されるか、 トップレベルREPLから直接loadされる場合です。

この関数がスクリプト実行期間中以外に呼ばれた場合は#fが返ります。

Variable: *program-name*
Variable: *argv*

Deprecated. これらの変数はそれぞれ、プログラム名および、コマンドライン引数のリストに束縛されます。 goshを使ってGaucheスクリプトを実行しているなら、*program-name*は (goshに与えられたとおりの) スクリプト名になっています。goshが インタラクティブREPLとして起動された場合は*program-name*は 空文字列""で、*argv*は空リストです。

これらの変数はuserモジュールにあります。

これは主として互換性のためだけに残されています。STkと互換な名前ですが、 他のScheme実装へはポータブルではありません。上のcommand-lineパラメータの 方がお勧めです。

Gaucheが埋め込み言語として使われている場合、これらの変数を設定するかどうかは ホストアプリケーションに任されます。一般には、これらの変数が必ず存在している とは限りません。これもまた、他の方法を使うべき理由です。


6.24.3 環境の問い合わせ

Function: sys-getenv name

[POSIX] 環境変数nameの値を文字列で返します。もしnameが定義されていなければ、 #fが返ります。

ポータブルなコードでは、SRFI-98およびR7RSのget-environment-variableを 使うのが良いでしょう(srfi.98 - 環境変数へのアクセス参照)。

註: 多くのシステムでは、環境が変更されている最中のgetenvのスレッド安全性を 保証していませんが、Gaucheは内部的に環境へのアクセスと変更のAPIを排他制御しているので、 Gaucheの手続きを使っている限りにおいてはスレッド安全です。

Function: sys-environ

現在の環境を文字列のリストとして返します。それぞれの文字列は NAME=VALUEというフォーマットになっています。ここでNAMEは 環境変数名、VALUEはその値です。NAMEが文字#\=を含 むことはありません。この手続きは現在のプロセスの環境変数をすべて取得し たい場合に便利です。特定の環境変数の値が欲しい場合には sys-getenvを使ってください。

Function: sys-environ->alist :optional envlist

sys-environの便利版。環境リスト(sys-environが返すような 形式のもの)をenvlistとして与えると、この手続きは各環境変数を名前 と値に分けて連想リストにして返します。

envlistを省略すると、この手続きはsys-environを呼んで現在 の環境変数を取得します。

ポータブルなコードでは、SRFI-98およびR7RSの get-environment-variables (srfi.98 - 環境変数へのアクセス参照), を使うのが良いでしょう。

(sys-environ->alist '("A=B" "C=D=E"))
  => (("A" . "B") ("C" . "D=E"))
Function: sys-setenv name value :optional overwrite
Function: sys-putenv name=value

sys-setenvは環境変数nameとその値valueを プロセスの実行環境に挿入します。 ただし、省略可能引数overwrite#f(デフォルト値)の場合、 nameが既に存在したら実行環境は変更されません。 overwriteが真の値であれば、環境変数は上書きされます。

sys-putenvでは、環境変数を名前と値を#\=でつないだ NAME=VALUEという形式で指定します。 同名の環境変数が既に存在する場合は常に上書きされます。

これらのAPIはPOSIXのsetenv(3)putenv(3)のインタフェースを 反映しています。しかし、putenv(3)と違って sys-putenvに渡した文字列はコピーされるので、後でその文字列を 破壊的変更してもプロセスの実行環境に影響はありません。

これらの手続きは機能識別子gauche.sys.setenvがある場合のみ使えます。 下の例のようにcond-expandで使えるかどうかチェックしてください (機能条件式参照)。

(cond-expand
 [gauche.sys.setenv
   ... use sys-setenv or sys-putenv ... ]
 [else
   ... fallback code ...])

これらの手続きは、他の方法で環境変数を変更しない限り、スレッドセーフです。

Function: sys-unsetenv name
Function: sys-clearenv

sys-unsetenvは環境変数nameを、また sys-clearenvは全ての環境変数をプロセスの実行環境から取り除きます。 sys-clearenvは、子プロセスを走らせる際に予期せぬ環境変数を 注入されないようにするのに便利です。

これらの手続きは機能識別子gauche.sys.unsetenvがある場合のみ使えます。 下の例のようにcond-expandで使えるかどうかチェックしてください (機能条件式参照)。

(cond-expand
 [gauche.sys.unsetenv
   ... use sys-unsetenv or sys-clearenv ... ]
 [else
   ... fallback code ...])

SRFI-98 (srfi.98 - 環境変数へのアクセス参照) にも、 環境変数を読み出すための、上記の手続きのサブセットにあたるものが 定義されています。ポータブルなコードにしたければそちらも見てみてください。

Function: gauche-version
Function: gauche-architecture
Function: gauche-library-directory
Function: gauche-architecture-directory
Function: gauche-site-library-directory
Function: gauche-site-architecture-directory

これらの手続きはGaucheランタイムの情報を文字列で返します。

Function: version-alist

[SRFI-176] 様々なランタイムの情報をalistで返します。 gosh -Vで表示される情報と同じです。

結果は環境変数GAUCHE_VERSION_INFO_EXCLUSIONに影響を受けます。 詳しくは環境変数を参照してください。

Function: sys-available-processors

現在Gaucheが走っているプラットフォームで使えるプロセッサの個数を返します。 戻り値は常に正の正確な整数です。Gaucheがこの情報を入手できなかった場合は 1が返ります。

但し、もし環境変数GAUCHE_AVAILABLE_PROCESSORSが定義されていて、 その値が正の整数と解釈できるものだった場合、ハードウェア/OSがどう言おうと 環境変数の値が返されます。


6.24.4 ファイルシステム

ファイルシステムに関するシステムコール群です。 ここで述べる手続きの上に、より高レベルなAPIがモジュールfile.utilとして 実装されています。file.util - ファイルシステムユーティリティを参照して下さい。


6.24.4.1 ディレクトリ

高レベルAPIに関してはディレクトリユーティリティも参照して下さい。

Function: sys-readdir path

pathは存在するディレクトリを示すパス名でなければなりません。 この手続きはディレクトリの全エントリを文字列のリストとして返します。 リストはソートされません。pathが存在しなかったり、ディレクトリでなかった場合は エラーとなります。

Function: glob pattern :key separator folder sorter
Function: sys-glob pattern :key separator folder sorter

伝統的なUnixのglob(3)の機能を提供します。この手続きはpatternとマッ チするパス名のリストを返します。

この機能は、かつてはプラットフォームが提供するglob関数をラップする もので、sys-globという名前でした。しかし、プラットフォーム間の非互 換性を解消し機能の追加を容易にするために、Gauche 0.8.12以降、システムコー ルの上にSchemeで再実装されています。そのため、globと改名してあ ります。古い方の名前sys-globは互換性のために残してありますが、 新たにプログラムを書くときはglobを使ってください。

引数patternは単一のグロブパターンもしくは、グ ロブパターンのリストです。リストが渡されたときには、 最低1つのパターンにマッチするパス名がすべて返されます。 Unixのユーザならglobの動作は馴染み深いものでしょう。

gosh> (glob "*.scm")
("ext.scm" "test.scm")
gosh> (glob "src/*.[ch]")
("src/ext.c" "src/ext.h")
gosh> (glob '("*.scm" "src/*.c"))
("ext.scm" "src/ext.c" "test.scm")

シェルのグロブとはちがって、マッチするパス名がないときは、()が返ります。

デフォルトでは、結果は組み込みのsort手続きによりソートされて返されます (ソートとマージ参照)。sorterキーワード引数で 代わりのソート手続きを指定できます。sorter手続きはひとつのリストを受け取り、 それをソートして返します。また、sorter引数に#fを渡すと、 結果はソートされずに返されます。

グロブはファイルシステムに限らず階層的なデータ構造を検索するのに非常に便利なツールです。 したがって、glob関数はファイルシステムからは切り離して実装されています。 キーワード引数を使うことで、どのようなツリー状のデータ構造からでもグロブできます。 デフォルト値がファイルシステム用に設定されているにすぎません。

引数separatorは文字の集合を与えます。これを使ってpatternを コンポーネントに分割します。デフォルトは#[/]です。実際のパス名 をマッチさせるのには使われません。

folderはデータ構造をトラバースするための手続きです。この手続きは 引数を5つとります。

(folder proc seed parent regexp non-leaf?)

procは引数を2つ取る手続きです。folderは、parent内で コンポーネントとなる名前がregexpとマッチする各ノードと、 foldと同様に順に渡されるシード値とで、procを呼びます。 folderprocが最後に返した値を返します。たとえば、 consprocとして、()seedとして渡されれば、 folder手続きが返す値はregexpとマッチするノードのリストになります。

ノードの表現がどうなるかはfolderの実装によります。 パス名であったり、オブジェクトであったりするかもしれません。 glob手続きはノードの表現については感知しません。 glob手続きがやることはノードを次に呼ぶ folderparent引数として渡して、 その結果のノードリストを返すだけです。

parent引数は基本的にはノードで、folderはその子ノードを 対象にマッチするものを探索します。 例外は最初にfolderが呼ばれる時です。その時点ではglobは ノードについて何も知らないので、 絶対パスでマッチをかける場合は#tを、 相対パスでマッチをかける場合は#fを最初のparentの値として渡します。

regexp引数は子ノードをフィルターするのに使い、ディレクトリ名を含 まない、子のコンポーネントである名前に対して照合されるものです。特別な 場合として、シンボルdir?にすることができます。この場合は、folder はnodeそのものを返し、nodeディレクトリと見なされ ます。すなわち、nodeがパス名を表わす場合には、folderはディレクト リ区切り子が最後に付いたパス名を返します。 特別な場合として、nodeがブール値でかつ regexpdir?である場合、folderはルートノードをあらわすノー ドあるいはカレントノードを返すことになっています。すなわち、node はパス名を表す場合、folderは"/"または"./"を返します。

non-leaf引数はブール値フラッグです。真なら、フィルタは結果からリー フノードをのぞきます(すなわち、ディレクトリだけが含まれるようになり ます)。

ここからはグロブパターンマッチングの細かい仕様をみていきます。

各グロブパターンはパス名様式文字列にマッチする文字列です。

パス名様式文字列は1つ以上のセパレータで区切られた コンポーネントから構成される文字列です。 デフォルトのセパレータは#[/]です。キーワード引数separator を使うとこれを変更できます。コンポーネントにはセパレータを含められませ ん。また空文字列にすることもできません。連続したセパレータは単一のセパ レータとみなされます。パス名様式の文字列は状況に応じてセパレータから始 めたり、セパレータで終端したりできます(両方をやるのも可)。

グロブパターンもコンポーネントとセパレータ文字から構成されます。コンポー ネントにおいては、以下の文字、構文は特別な意味を持ちます。

*

これがコンポーネントの先頭に表われた場合、0個以上のピリオド(.) を除く文字にマッチします。入力文字列のコンポーネントがピリオドではじま るような文字列の場合にはマッチしません。

先頭以外の場所では、0個以上の文字の列にマッチします。

**

コンポーネントが**だけの場合、これは*にマッチする0個以上の コンポーネントにマッチします。例えばsrc/**/*.hは 次のようなパターン全てにマッチします。

src/*.h
src/*/*.h
src/*/*/*.h
src/*/*/*/*.h
...
?

コンポーネントの先頭にあらわれた場合、ピリオド(.)以外の一文字に マッチします。先頭以外の場所では任意の一文字にマッチします。

[chars]

文字の集合を指定します。その集合に含まれる文字のどれかにマッチします。 charsの構文はGaucheの文字集合を表す構文と同じです (文字集合参照)。伝統的なグロブとの互換性のために、! 文字をつかって、補集合で文字集合を表わすこともできるようになっています。 すなわち、[!abc][^abc]と同じです。

\

次の文字をそのままパターンに含めます。上の特殊文字をそのままパターンに入れたい 時に使えます。

Function: glob-fold pattern proc seed :key separator folder sorter

これはグロブ関数の低レベル版です。実際globは以下のように書いたの と同じです。

(define (glob patterns . opts)
  (apply glob-fold patterns cons '() opts))

patternseparatorfolderおよびsorterの意味を前述のものと同 じです。

patternにパス名ごとにglob-foldprocをパス名とシー ド値で呼びます。最初のシード値はseedで、procが返す値は次の シード値になります。最後のprocの呼び出し結果はglob-foldの 結果となります。マッチするパス名が存在しないときは、procは呼ばれ ずに、seedが返ります。

Function: make-glob-fs-fold :key root-path current-path

これはglob-foldglobfolderキーワード引数に 渡せる形の手続きを作るユーティリティ手続きです。 引数を渡さなければ、glob-foldglobがデフォルトで使うのと 同じ手続きが返ります。

キーワード引数root-pathおよびcurrent-pathはそれぞれ、 glob-foldが探索を開始するディレクトリを指定します。

gosh> (glob "/tmp/*.scm")
("/tmp/x.scm" "/tmp/y.scm")
gosh> (glob "/*.scm"
            :folder (make-glob-fs-fold :root-path "/tmp"))
("/tmp/x.scm" "/tmp/y.scm")
gosh> (glob "*.scm"
            :folder (make-glob-fs-fold :current-path "/tmp"))
("/tmp/x.scm" "/tmp/y.scm")

パスがディレクトリかどうかチェックする方法は、ファイルの状態を参照してください。


6.24.4.2 ディレクトリ操作

Function: sys-remove filename

[POSIX] filenameがファイルであればそれを消去します。 システムによってはfilenameが空のディレクトリであっても動作しますが、 移植性を気にする場合はその動作に依存しない方が良いでしょう。

Function: sys-rename old new

[POSIX] ファイルoldnewにリネームします。新しい名前は 古い名前と異なるディレクトリにあってもかまいませんが、両者は同じデバイス上に なければなりません。

Function: sys-tmpnam

[POSIX] ユニークなファイル名を作成して返します。この関数はPOSIXに含まれていますが、 セキュリティ上の問題が指摘されており、使わない方が良いとされています。 可能なら下にあげるsys-mkstempを使って下さい。

Function: sys-mkstemp template

ユニークな名前を持つファイルを作成してオープンし、オープンされたポートとファイル名の 二つの値を返します。ファイルは排他的に作成されるため、レースコンディションは起こりません。 templateはファイル名のプレフィックスに使われます。Unixのmkstempと違って、 パディングキャラクタをつける必要はありません。ファイルは書き込み用としてオープンされ、 パーミッションは600にセットされます。

Function: sys-mkdtemp template

ユニークな名前を持つディレクトリを作成し、その名前を返します。 templateはディレクトリ名のプレフィックスに使われます。 Unixのmkdtempと違って、パディングキャラクタをつける必要はありません。 ディレクトリのパーミッションは700にセットされます。

[POSIX] 既存のファイルexistingに対し、newという名のハードリンクを作成します。

[POSIX] pathnameで示されるファイルを消去します。 pathnameはディレクトリであってはなりません。 もし消去に成功したら#tが、pathnameが存在しなければ#fが返されます。 他の場合はエラーが通知されます。

file.utilモジュールに似た手続きdelete-file/remove-fileが ありますが、そちらはファイルが存在しない場合にエラーを投げます (ファイル操作参照)。

R7RSはdelete-fileを定義しています。ポータブルなプログラムでは そちらを使うのが良いでしょう。

existingを指すnewという名のシンボリックを作成します。 シンボリックリンクをサポートしないシステムでは、この手続きは定義されません。

pathで示されるファイルがシンボリックリンクならば、それが指すパスを返します。 もしpathが存在しなかったり、シンボリックリンクでなければ、エラーが通知されます。 シンボリックリンクをサポートしないシステムでは、この手続きは定義されません。

Function: sys-mkdir pathname mode

[POSIX] ディレクトリpathnameをモードmodeで作成します。 (modeはさらにumaskでマスクされることに注意して下さい;下のsys-umask 参照)。 pathnameの親ディレクトリは存在して、プロセスが書き込めるようになっていなければ なりません。中間のディレクトリも一度に作成するには、 file.utilmake-directory*が使えます (ディレクトリユーティリティ)。

Function: sys-rmdir pathname

[POSIX] ディレクトリpathnameを消去します。ディレクトリは空でなければなりません。 ディレクトリの内容も一緒に消去するには、file.utilremove-directory* が使えます(ディレクトリユーティリティ)。

Function: sys-umask :optional mode

[POSIX] umaskをmodeにセットします。変更される前のumaskを返します。 modeが省略されるか#fが渡された場合、 現在のumaskを変更せずにその値を返します。 umaskについてはman umaskを参照してください。


6.24.4.3 パス名

高レベルのAPIに関してはパスネームユーティリティも参照して下さい。

Function: sys-normalize-pathname pathname :key absolute expand canonicalize

与えられたキーワード引数によってpathnameを以下のように変換します。 キーワード引数は同時に複数指定できます。

absolute

このキーワード引数に真の値が与えられて、pathnameが絶対パスでない場合、 pathnameの前にプロセスのワーキングディレクトリを足して絶対パスにします。

expand

このキーワード引数に真の値が与えられて、pathnameが‘~’ で始まっていた 場合、以下のように展開されます。

  • pathnameが“~”のみであるか、または“~/”で始まっている 場合、文字“~”が現在のプロセスのユーザのホームディレクトリに置き換えられます。
  • 上記以外の場合、‘~’以降、‘/’かpathnameの終端までの文字列 がユーザ名とみなされ、そのユーザのホームディレクトリに置換されます。もし該当するユーザが いなければエラーとなります。
canonicalize

パス名から “.” や “..” を除き、単純化します。 この操作は実際のファイルシステムを参照せずに行われます。元のパス名がディレクトリへの シンボリックリンクを含んでいた場合、単純化されたパス名は正しくないかもしれません。

Function: sys-basename pathname
Function: sys-dirname pathname

sys-basenameは与えられたパスのベース名、すなわち最後のコンポーネントを返します。 sys-dirnameは与えられたパスのディレクトリ名、すなわち最後のコンポーネント以外の コンポーネントを返します。pathnameの末尾が‘/’である場合、その文字は 無視されます。

(sys-basename "foo/bar/bar.z") ⇒ "bar.z"
(sys-basename "coo.scm") ⇒ "coo.scm"
(sys-basename "x/y/") ⇒ "y"
(sys-dirname "foo/bar/bar.z") ⇒ "foo/bar"
(sys-dirname "coo.scm") ⇒ "."
(sys-dirname "x/y/") ⇒ "x"

この手続きはpathnameが存在するかどうかはチェックしません。

特殊なケース:

(sys-basename "") ⇒ ""
(sys-dirname "") ⇒ "."

(sys-basename "/") ⇒ ""
(sys-dirname "/") ⇒ "/"

註:このふるまいはPerlのbasenameおよびdirnameと同様です。 システムによっては、コマンドのbasename"/"に対して"/"を、 "."に対して"."を返すものがあります。

Function: sys-realpath pathname

sys-realpathは“.”, “..”およびシンボリックリン クを含まないpathnameの絶対パスを返します。pathname自体が存在しなかったり、 存在しないパスを指すシンボリックリンクが含まれていたり、関連するパスへのアクセス権限が 不足している場合はエラーが通知されます。

注:POSIXのrealpath(3)は安全でない場合があるので、 Gaucheは内部でCランタイムのrealpathを呼ばずに、 独自にsys-realpathの機能を実装しています。

Function: sys-tmpdir

一時ファイルを置くためのデフォルトのディレクトリ名を返します。

Unix系システムでは、環境変数TMPDIRTMPがこの順でチェックされ、 フォールバックとして/tmpが返されます。

Windowsネイティブの環境では、GetTempPath Windows APIを呼びます。 これは環境変数TMPTEMPUSERPROFILEを順に調べ、 いずれも定義されていなければWindowsシステムディレクトリを返します。

いずれのプラットフォームでも、返されたパス名は存在しないかもしれず、 また書き込み可能ではないかもしれないことに注意してください。

一般的に、ユーザプログラムやライブラリはtemporary-directory (ディレクトリユーティリティ参照) の方を利用するのが良いでしょう。 sys-tmpdirはプラットフォームが推奨する生の値を知りたい場合に 限り使ってください。


6.24.4.4 ファイルの状態

高レベルのAPIに関してはファイル属性ユーティリティも参照して下さい。

Function: file-exists? path

[R7RS file] pathが存在していれば#tを返します。

Function: file-is-regular? path
Function: file-is-directory? path

それぞれ、pathが存在するか、存在してそれがレギュラーファイルであるか、 存在してそれがディレクトリであれば#tを返します。

Builtin Class: <sys-stat>

ファイルシステム内のエントリの属性を表す、struct statのラッパー オブジェクトです。以下に示す読みだし専用のスロットを持ちます。

Instance Variable of <sys-stat>: type

ファイルのタイプを示すシンボルです。

regular通常のファイル
directoryディレクトリ
characterキャラクタデバイス
blockブロックデバイス
fifoFIFO
symlinkシンボリックリンク
socketソケット

以上のどれにも当てはまらない場合は#fが返されます。

注:いくつかのオペレーティングシステムではsocketファイルタイプを fifoと区別せず、どちらに対してもfifoを返します。 ポータブルなプログラムを書くときは注意して下さい。

Instance Variable of <sys-stat>: perm

パーミッションビットマスク。"mode"スロットの下位9ビットと同じですが、 便利なので独立したスロットとして提供されます。

Instance Variable of <sys-stat>: mode
Instance Variable of <sys-stat>: ino
Instance Variable of <sys-stat>: dev
Instance Variable of <sys-stat>: rdev
Instance Variable of <sys-stat>: uid
Instance Variable of <sys-stat>: gid
Instance Variable of <sys-stat>: size

struct statの該当するフィールドの値。正確な整数です。

Instance Variable of <sys-stat>: atime
Instance Variable of <sys-stat>: mtime
Instance Variable of <sys-stat>: ctime

struct statの該当するフィールドの値を、Unix Epochからの秒数で。

Instance Variable of <sys-stat>: atim
Instance Variable of <sys-stat>: mtim
Instance Variable of <sys-stat>: ctim

<time>オブジェクトで表されたタイムスタンプ (時間参照)。 システムがサポートしていれば、ナノ秒単位のタイムスタンプを得ることができます。

Function: sys-stat path
Function: sys-fstat port-or-fd

[POSIX] 与えられたパス名path、またはポートかファイルディスクリプタ port-or-fdで示されるファイルの情報を<sys-stat>オブジェクトで 返します。

sys-statは、pathがシンボリックリンクであった場合は リンクの指す先のファイルに関する情報を返します。

sys-fstatは、port-or-fdがファイルに関係ないポートであった 場合は#fを返します。

Function: sys-lstat path

sys-statと同じですが、pathがシンボリックリンクであった 場合はリンクそのものの情報を返します。

gosh> (describe (sys-stat "gauche.h"))
#<<sys-stat> 0x815af70> is an instance of class <sys-stat>
slots:
  type      : regular
  perm      : 420
  mode      : 33188
  ino       : 845140
  dev       : 774
  rdev      : 0
  nlink     : 1
  uid       : 400
  gid       : 100
  size      : 79549
  atime     : 1020155914
  mtime     : 1020152005
  ctime     : 1020152005
Function: sys-stat->mode stat
Function: sys-stat->ino stat
Function: sys-stat->dev stat
Function: sys-stat->rdev stat
Function: sys-stat->size stat
Function: sys-stat->uid stat
Function: sys-stat->gid stat
Function: sys-stat->atime stat
Function: sys-stat->mtime stat
Function: sys-stat->ctime stat
Function: sys-stat->file-type stat

Deprecated. <sys-stat>オブジェクトの情報にアクセスするにはslot-refを 使って下さい。

Function: sys-access pathname amode

[POSIX] pathnameへのアクセスが modeに示されるモードで許可されているかどうかを示す真偽値を返します。 この手続きは、suid/sgidプログラムで使われるとエラーとなります(下記註参照)。 modeは以下に示す定数のコンビネーション(logical or)です。

R_OK

pathnameをカレントユーザが読み出し可能かどうか

W_OK

pathnameへカレントユーザが書き込み可能かどうか

X_OK

pathnameをカレントユーザが実行可能かどうか(pathnameが ディレクトリの場合はサーチ可能かどうか)

F_OK

pathnameのパーミッションフラグにかかわらず、pathnameが 存在するかどうか (但しpathnameがあるディレクトリの読みだし許可は必要)。

註: access(2)は、suid/sgidプログラム中で 実ユーザの権限を確かめるために使われた場合、セキュリティホールと なります。

Function: sys-chmod path mode
Function: sys-fchmod port-or-fd mode

名前pathを持つ、もしくはport-or-fdで指定される ファイルのパーミッションビットをmodeに変更します。 modeは小さな正の正確な整数で、POSIXスタイルのパーミッションビットマスク でなければなりません。

Function: sys-chown path owner-id group-id

ファイルpathのオーナーとグループをowner-idgroup-id で示されるものに変更します。owner-idgroup-idは正確な整数で なければなりません。どちらかに-1が渡された場合は、対応する情報は変更されません。

Function: sys-utime path :optional atime mtime

ファイルのアクセスタイムと変更タイムをatimemtimeが示す 値にセットします。atime/mtime引数に許されるのは、 #f (現在の時刻)、#t (変更なし)、 実数 (Epochからの秒数)、あるいは<time>インスタンスです (時間参照)。

ファイル操作touch-fileも参照して下さい。


6.24.4.5 他のファイル操作

Function: sys-chdir dir

[POSIX] chdir(2)へのインタフェースです。 current-directory(ディレクトリユーティリティ)も参照して下さい。

Function: sys-pipe :key (buffering :line)

[POSIX] パイプを作り、ポートを2つ返します。 最初に返されるポートは入力ポートで、2番目に返されるポートは出力ポートです。 出力ポートへ書き出したデータは、入力ポートから読み込めます。

buffering:full:line:noneのいずれかで、 パイプ上に開かれたポートのバッファリングモードを指定します。 バッファリングモードの詳細については、ファイルポートを参照して下さい。 通常のケースでは、デフォルトのモードで間に合うでしょう。

(receive (in out) (sys-pipe)
  (display "abc\n" out)
  (flush out)
  (read-line in)) ⇒ "abc"

注意: 戻り値はバージョン0.3.15から変更されています。それまでは、 sys-pipeは2つのポートのリストを返します。

Function: sys-mkfifo path mode

[POSIX] 名前がpathでモードがmodeのFIFO(名前付きパイプ)を 作ります。modeはファイルのモードを表す正の正確整数でなければ なりません。

Function: sys-isatty port-or-fd

[POSIX] port-or-fdはポートか整数のファイルディスクリプタです。 ポートがコンソールに接続されていれば#tを、そうでなければ#fを 返します。

Function: sys-ttyname port-or-fd

[POSIX] port-or-fdはポートか整数のファイルディスクリプタです。 ポートに接続された端末の名前か、ポートが端末に接続されていなければ #fを返します。

Function: sys-truncate path length
Function: sys-ftruncate port-or-fd length

[POSIX] pathあるいはport-or-fdによって指定される通常ファイルの長さを lengthにします。 ファイルがlengthより長かった場合、余分なデータは捨てられます。 ファイルがlengthより短かった場合、残りの部分にはゼロが詰められます。


6.24.5 Unixのグループとユーザ

Unix groups

Builtin Class: <sys-group>

Unixのグループの情報です。以下のスロットを持ちます。

Instance Variable of <sys-group>: name

グループ名。

Instance Variable of <sys-group>: gid

グループID

Instance Variable of <sys-group>: passwd

グループパスワード。

Instance Variable of <sys-group>: mem

このグループに属するユーザ名のリスト。

Function: sys-getgrgid gid
Function: sys-getgrnam name

[POSIX] グループIDgidもしくはグループ名nameで示されるグループの情報を <sys-group>で返します。該当するグループが存在しない場合は #fが返されます。

Function: sys-gid->group-name gid
Function: sys-group-name->gid name

グループIDとグループ名を相互変換する便利な手続きです。

Unix users

Builtin Class: <sys-passwd>

Unixのユーザの情報です。以下のスロットを持ちます。

Instance Variable of <sys-passwd>: name

ユーザ名。

Instance Variable of <sys-passwd>: uid

ユーザID

Instance Variable of <sys-passwd>: gid

ユーザのプライマリグループID。

Instance Variable of <sys-passwd>: passwd

ユーザの(暗号化された)パスワード。システムがシャドウパスワードファイルを 使っている場合は、 "x" のような無意味な文字列が入っています。

Instance Variable of <sys-passwd>: gecos

Gecosフィールド。

Instance Variable of <sys-passwd>: dir

ユーザのホームディレクトリ。

Instance Variable of <sys-passwd>: shell

ユーザのログインシェル。

Instance Variable of <sys-passwd>: class

ユーザのクラス。(特定のシステムでのみ有効)。

Function: sys-getpwuid uid
Function: sys-getpwnam name

[POSIX] ユーザIDuidもしくはユーザ名nameで示されるユーザの情報を <sys-passwd>で返します。該当するユーザが存在しない場合は #fが返されます。

Function: sys-uid->user-name uid
Function: sys-user-name->uid name

ユーザIDとユーザ名を相互変換する便利な手続きです。

Password encryption

Function: sys-crypt key salt

これは、crypt(3)へのインターフェースです。keysaltは 文字列でなければならず、暗号化された文字列が返されます。 crypt(3)が利用できないシステムでこの関数を呼ぶとエラーが通知されます。

このルーチンは、システムのパスワードデータベースを使ってパスワードチェックを しなければならない時以外に使うべきではありません。独自のパスワードデータベースを 新たに作る場合は、crypt.bcryptモジュール(crypt.bcrypt - パスワードハッシュ)を 使ってください。


6.24.6 ロケール

Function: sys-setlocale category locale

[POSIX] カテゴリーcategoryのロケールをlocaleにセットします。 categoryは整数でなければなりません;以下の変数がcategoryの ために定義されています。localeはロケールを表す文字列か#fです。

成功した場合は新しいロケール名を、ロケールが変更できなかった場合は#fを 返します。locale#fを渡した場合は、ロケールの変更はせずに 単に現在のロケールの値を文字列で返します。

Variable: LC_ALL
Variable: LC_COLLATE
Variable: LC_CTYPE
Variable: LC_MONETARY
Variable: LC_NUMERIC
Variable: LC_TIME

sys-setlocalecategoryに渡せる数値を定義しています。

Function: sys-localeconv

[POSIX] 現在のロケールで数値をフォーマットする際に必要な様々な情報をassoc listに して返します。

例を示します。あなたのシステム設定によっては異なる結果になるかもしれません。

(sys-localeconv)
 ⇒
   ((decimal_point . ".") (thousands_sep . "")
    (grouping . "") (int_curr_symbol . "")
    (currency_symbol . "") (mon_decimal_point . "")
    (mon_thousands_sep . "") (mon_grouping . "")
    (positive_sign . "") (negative_sign . "")
    (int_frac_digits . 127) (frac_digits . 127)
    (p_cs_precedes . #t) (p_sep_by_space . #t)
    (n_cs_precedes . #t) (n_sep_by_space . #t)
    (p_sign_posn . 127) (n_sign_posn . 127))

(sys-setlocale LC_ALL "fr_FR")
 ⇒ "fr_FR"

(sys-localeconv)
 ⇒
  ((decimal_point . ",") (thousands_sep . "")
   (grouping . "") (int_curr_symbol . "FRF ")
   (currency_symbol . "F") (mon_decimal_point . ",")
   (mon_thousands_sep . " ") (mon_grouping . "\x03\x03")
   (positive_sign . "") (negative_sign . "-")
   (int_frac_digits . 2) (frac_digits . 2)
   (p_cs_precedes . #f) (p_sep_by_space . #t)
   (n_cs_precedes . #f) (n_sep_by_space . #t)
   (p_sign_posn . 1) (n_sign_posn . 1))

6.24.7 シグナル

Gaucheでは、OSのシグナルを自分自身や他のプロセスに送ったり、 送られたシグナルを処理することができます。

マルチスレッド環境では、全てのスレッドがシグナルハンドラを共有し、 各スレッドが独自のシグナルマスクを持ちます。 詳しくはシグナルとスレッドを参照して下さい。

システムコールがシグナルによって割り込まれ、 プログラマがシグナルハンドラをセットしており、そのハンドラが別コンテキストに 制御を移さずに戻った場合、そのシステムコールは原則としてハンドラからの復帰後に リスタートされます。

シグナル割り込みによって単純にリスタートされないものは次の通りです。

close

これはsys-closeclose-port、さらには低層のファイルが自動的に クローズされる場合に呼ばれます。シグナルがこのシステムコールを中断してEINTRが 返った時点で、渡されたファイルディスクリプタは無効になっており、もし他のスレッドがその ディスクリプタを直後に再利用していたら、リスタートするのは競合を引き起こします。

dup2

このコールはport-fd-dup!から呼ばれます。dup2EINTRを 返した時、newfdは使われない状態になっており、他のスレッドが直後にそれを使う 可能性があるのでリスタートは危険です。

sleep
nanosleep

これらのコールは中断された場合に残りの時間を教えてくれます。 Gaucheではリスタート時に元の引数でなく残りの時間を渡すので、スリープする全体の時間は おおよそ最初に与えられた時間となります。

Windowsネイティブ環境では、sys-killの限定的なサポートを 除いてシグナルは動作しません。


6.24.7.1 シグナルとシグナルセット

シグナルはオペレーティングシステムで定義された小さな整数値で表現されます。 システムのシグナル番号に束縛された変数が定義されています。 システムのシグナル番号はアーキテクチャによって異なるので、 なるべく変数を利用するようにして下さい。

Variable: SIGABRT
Variable: SIGALRM
Variable: SIGCHLD
Variable: SIGCONT
Variable: SIGFPE
Variable: SIGHUP
Variable: SIGILL
Variable: SIGINT
Variable: SIGKILL
Variable: SIGPIPE
Variable: SIGQUIT
Variable: SIGSEGV
Variable: SIGSTOP
Variable: SIGTERM
Variable: SIGTSTP
Variable: SIGTTIN
Variable: SIGTTOU
Variable: SIGUSR1
Variable: SIGUSR2

これらの変数はPOSIXで定義された対応するシグナルの番号に束縛されています。

Variable: SIGTRAP
Variable: SIGIOT
Variable: SIGBUS
Variable: SIGSTKFLT
Variable: SIGURG
Variable: SIGXCPU
Variable: SIGXFSZ
Variable: SIGVTALRM
Variable: SIGPROF
Variable: SIGWINCH
Variable: SIGPOLL
Variable: SIGIO
Variable: SIGPWR

これらの変数はシステム依存のシグナル番号に束縛されています。 全てのシステムで全てのシグナルがサポートされているわけではありません。

ポータブルなコードには、SRFI-238のコードセットを使うこともできます (srfi.238 - コードセット参照)。

それぞれのシグナル番号の他に、<sys-sigset>オブジェクトを使って シグナルの集合を扱うことができます。シグナルの集合はシグナルマスクを操作したり、 ひとつのシグナルハンドラを多数のシグナルに同時に設定したりする際に使えます。

Function: sys-strsignal signum

[POSIX] strsignal(3)へのインタフェースです。引数は正確な整数でなければなりません。

シグナル番号signumのシグナルに結びつけられたメッセージを文字列で返します。 もしメッセージが無かったり、signumが有効なシグナル番号でなかったら、 この関数は#fを返すか、システムが提供する一般的なメッセージを返します。

ポータブルなコードには、SRFI-238のコードセットを使うこともできます (srfi.238 - コードセット参照)。

Class: <sys-sigset>

シグナルの集合を表します。空のシグナルの集合は次の式で作成できます:

(make <sys-sigset>) ⇒ #<sys-sigset []>
Function: sys-sigset signal …

signal …をメンバーとする<sys-sigset>の インスタンスを作成して返します。 各signalにはシグナル番号、他の<sys-sigset>オブジェクト、あるいは #tを渡すことができます。#tを渡した場合は全てのシグナルが 対象となります。

(sys-sigset SIGHUP SIGINT) ⇒ #<sys-sigset [HUP|INT]>
Function: sys-sigset-add! sigset signal …
Function: sys-sigset-delete! sigset signal …

sigset<sys-sigset>オブジェクトでなければなりません。 これらの手続きはsigsetに指定されたシグナルを追加、 もしくはsigsetから指定されたシグナルを削除します。 変更されたsigsetが返されます。

signalにはシグナル番号、他の<sys-sigset>オブジェクト、あるいは #tを渡すことができます。#tを渡した場合は全てのシグナルが 対象となります。

Function: sys-sigset-fill! sigset
Function: sys-sigset-empty! sigset

システムで定義された全てのシグナルをsigsetにセット、 もしくはsigsetを空にします。

Function: sys-signal-name signal

シグナル番号の名前を返します。(シグナル番号はシステムに依存します)。

ポータブルなコードには、SRFI-238のコードセットを使うこともできます (srfi.238 - コードセット参照)。

(sys-signal-name 2) ⇒ "SIGINT"

6.24.7.2 シグナルの送出

シグナルを送るには、sys-killを使うことができます。 これはシステムのkill(2)のように動作します。

Function: sys-kill pid sig

[POSIX] シグナルsigを指定されたプロセス(群)に送ります。 sigは正確な正整数でなければなりません。pidは正確な整数でなければ ならず、次のルールで対象となるプロセスを指定します。

  • pidが正ならば、それがそのまま対象となるプロセスIDです。
  • pidがゼロならば、シグナルは現在のプロセスのプロセスグループ内の全ての プロセスに送られます。
  • pidが-1より小さければ、シグナルはプロセスグループIDが-pidである 全てのプロセスに送られます。

Windowsネイティブ環境では、sys-killpidに正整数か プロセスハンドル(<win:handle>のインスタンス)を取ります。 sigがサポートするのはSIGKILLSIGINTSIGABRT のみです。SIGKILLに対してはTerminateProcessを使って 対象プロセスを終了させます。SIGINTSIGABRTに対しては 対象プロセスにそれぞれCTRL_C_EVENTCTRL_BREAK_EVENTを 送ります。

POSIXのraise()に対応するScheme関数はありませんが、 (sys-kill (sys-getpid) sig) で同じことができます。


6.24.7.3 シグナルの処理

Schemeでシグナルを処理する手続きを登録できます。 (マルチスレッド環境では、シグナルハンドラの設定は全てのスレッドで共有されます。 シグナルとスレッドを参照して下さい)。

シグナルがSchemeプロセスに送られると、VMはそれを記録し、 VMの状態が一貫している「安全なポイント」に達した時に処理します。 シグナルがVMに記録され、しかしまだ処理されていない状態を、 シグナルが保留されていると呼ぶことにします。

(このメカニズムのため、SIGILLのようなシグナルはSchemeレベルでは 処理できません。そのシグナルを記録した後でプロセスが意味のある処理を続行できない からです)。

VMがシグナルを処理する前に同じシグナルが到着した場合、後に到着した方の シグナルは無効になります。(これは伝統的なUnixのシグナル処理と同様です)。 言い替えれば、各VM loop毎に、シグナルハンドラは各シグナルについて たかだか1回しか呼ばれません。

同じシグナルがたくさん保留された状態になった場合、 Gaucheは異常事態が起きたとみなし (例えばCルーチンで無限ループに 入った等)、プロセスをabortします。デフォルトではこの限界は かなり低い値(3)に設定されています。これは、インタラクティブスクリプトが 反応しなくなった場合にCtrl-Cを3回打てば強制終了できる、という場合を 想定しているためです。この限界を調べるカウンタはシグナル毎にあるので、 例えばSIGHUPがひとつ、SIGINTがふたつ保留になった、 といった場合はabortしません。この限界は下で述べるset-signal-pending-limit で変更することができます。

goshインタプリタを使っている場合、デフォルトでのシグナルの処理は 次のように設定されています。

SIGABRT, SIGILL, SIGKILL, SIGSTOP, SIGSEGV, SIGBUS

Schemeでは処理できません。goshではこれらのシグナルを受けると システムのデフォルトの動作をします。

SIGCHLD, SIGTSTP, SIGTTIN, SIGTTOU, SIGWINCH

goshは初期状態ではこれらのシグナルのハンドラを設定せず、 システムのデフォルトの振るまいに任せます。Schemeプログラムは必要ならば これらのシグナルのハンドラを設定できます。

SIGCONT

goshが入力編集モードで起動している場合は、端末状態を回復する シグナルハンドラが設定されています。それ以外の場合はシグナルハンドラは 設定されず、Schemeプログラムは必要ならば独自のハンドラを設定できます。

SIGHUP, SIGQUIT, SIGTERM

goshはこれらのシグナルに対して、終了コード0でアプリケーションを 終了するシグナルハンドラをセットします。

SIGPIPE

Goshは何もしないシグナルハンドラを設定します。 つまり、事実上このシグナルはデフォルトで無視されます。

この設計の意図は次のとおりです。Gaucheはシグナルの処理を安全な ポイントまで遅延するため、SIGPIPEはそれを発生させた システムコールがEPIPEを返した後で処理されることになります。 この事実によって、SIGPIPEを処理する必要性は大きく低下します。 書き出した先のパイプが壊れていた場合にはEPIPE<system-error> をハンドルすれば良いからです。

UnixのデフォルトのSIGPIPE処理は、プロセスを終了させます。 これは伝統的な、パイプでつないでゆくコマンドラインツールにとっては 便利な振る舞いです。下流のコマンドが失敗した場合、上流のコマンドは SIGPIPEを受け取るので、つながれたすべてのコマンドが 静かに終了するからです。 けれども、ソケットなど他の種類の出力に対しては、このシグナルは しばしば邪魔になります。

Gaucheは、この「パイプが詰まったら終了する」という慣習を、 ポートによってサポートします。ポートを「SIGPIPEを感知する」モード にセットすることができます。そのようなポートへの書き込みが EPIPEを発生させる状況になったら、プロセスが終了します。 デフォルトでは、標準出力および標準エラー出力のポートが このモードになっています。

SIGPWR, SIGXCPU, SIGUSR1, SIGUSR2

Linuxプラットフォームでスレッドを使用している場合は、 これらのシグナルはシステムで使用されるため、Schemeからは使用できません。 他のシステムではこれらのシグナルは下記の「他のシグナル」と同じ動作と なります。

他のシグナル

goshはデフォルトのシグナルハンドラを設定します。 デフォルトのシグナルハンドラは<unhandled-signal-error>コンディションを 通知します(コンディション参照)。 Schemeプログラムはシグナル毎に独自のハンドラを設定することが可能です。

goshでなく、他のアプリケーションに埋め込まれたGaucheを使っている場合、 Schemeレベルでのシグナルの使用をアプリケーションが制限している場合があります。

Schemeからシグナルハンドラを設定するには以下の手続きを使って下さい。

Function: set-signal-handler! signals handler :optional sigmask

signalsはシグナル番号か<sys-sigset>オブジェクト、 handler#t#f#<undef>、 一つの引数を取る手続きのいずれかでなければなりません。 handlerが手続きの場合、プロセスが指定されたシグナル(のうちのいずれか)を 受けた時に、そのシグナル番号を引数としてhandlerが呼ばれます。

デフォルトでは、handlerは、signalsに含まれる シグナルが(その時点で有効なシグナルマスクに加えて)ブロックされた状態で 実行されます。オプショナルなsigmask引数に <sys-sigset>オブジェクトを渡すことで、 ブロックすべきシグナルを明示することもできます。 ただ、シグナルマスクはスレッド毎であることに注意して下さい。 もし複数のスレッドがあるシグナルをブロックしていない場合、例えsigmask を指定していたとしても、ひとつのスレッドでhandlerを実行中に 別のスレッドで並行してhandlerが呼ばれる可能性はあります。 各スレッドのシグナルマスクを適切に設定することでそのようなケースを 避けるようにして下さい。

handlerの中でできる操作にはほとんど制限がありません。 handlerからエラーを投げたり、他の場所で補捉された継続を呼ぶことも できます。但し、handler内で補捉した継続はhandlerから 戻った時点で無効になります。

handler#tの場合、指定されたシグナルにはオペレーティングシステムの デフォルトの振るまいが設定されます。 handler#fの場合、指定されたシグナルは無視されます。

handler#<undef> (未定義値参照) であった場合は、 Gaucheはその時点のOSレベルのシグナルハンドラを変更しません。 この引数はset-signal-handler!に対してはあまり 意味を持ちません; 何もせずに返るだけだからです。 しかし、get-signal-handler#<undef>が 返った場合、Gaucheがそのシグナルハンドラを一度もいじっていないことを 示します。 (一度でもGaucheがシグナルハンドラをインストールした場合、 get-signal-handler#<undef>を再び 返すことはありません。)

マルチスレッドプログラムでは、 シグナルハンドラの設定はスレッド間で共有されることに注意して下さい。 ハンドラはシグナルを受けたスレッドで実行されます。 詳しくはシグナルとスレッドを参照して下さい。

Function: get-signal-handler signum
Function: get-signal-handler-mask signum

シグナルsignumに設定されたハンドラもしくはシグナルマスクを それぞれ返します。get-signal-handlerが返す値の意味については set-signal-handler!を参照してください。

Function: get-signal-handlers

現在の全てのシグナルハンドラの設定を連想リストにして返します。 返されるリストの各要素のcarには<sys-sigset>オブジェクトが、 cdrにはそれらのシグナルに対応するハンドラ(手続きもしくはブール値)がセットされて います。

Function: get-signal-pending-limit
Function: set-signal-pending-limit limit

それぞれ、同一のシグナルをいくつまで保留することを許すかの現在の限界値を 読み出し、また設定します。 同一のシグナルが限界値を越える回数、処理されないまま保留された場合、 Gaucheはプロセスを強制終了します。本節の冒頭の説明を参照してください。 limitは非負の正確な整数でなければなりません。 現在の実装では、limitに設定できる最大値は255です。 また、limitに0を設定すると、無制限にシグナルを保留できるようになります。

Macro: with-signal-handlers (handler-clause …) thunk

thunkの実行中だけシグナルハンドラを一時的に設定する便利なマクロです (このマクロは便利ですが下に述べるような多少危険な性質もあるので、 注意して使って下さい)。

handler-clauseは以下のいずれかの形式です

(signals expr …)

signalsは、評価された時に単独のシグナル番号、シグナル番号のリスト、 あるいは<sys-sigset>オブジェクトを生成する式でなければなりません。 signalsに含まれるシグナルを受け取った時に、expr …を 評価するようなハンドラを設定します。

(signals => handler)

signalsは上と同じです。signalsに含まれるシグナルに 対して、処理handlerを設定します。

handler#t#f、一つの引数を取る手続きのいずれか でなければなりません。 handlerが手続きの場合、プロセスが指定されたシグナル(のうちのいずれか)を 受けた時に、そのシグナル番号を引数としてhandlerが呼ばれます。 handler#tの場合、指定されたシグナルにはオペレーティングシステムの デフォルトの振るまいが設定されます。 handler#fの場合、指定されたシグナルは無視されます。

thunkから制御が抜けた時に、with-signal-handlersが呼ばれた時点での シグナルハンドラが再設定されます。

注意: このフォームで一つ以上のシグナルハンドラを設定する場合、 それらは順にシステムに設定されます。全てのハンドラの設定が終る前に シグナルが届いた場合、シグナルハンドラの設定や再設定が不完全なままになる かもしれません。また、シグナルハンドラはグローバルな設定であり、 「スレッドローカル」なハンドラを設定することはできませんが、 with-signal-handlersの形式はそれを誤解させるかもしれません。


6.24.7.4 シグナルのマスクと待機

Schemeプログラムで、送出がブロックされるシグナルの集合であるシグナルマスク をセットできます。プロセスで完全にブロックされるシグナルが送出されると、 そのシグナルは“保留”となります。保留されたシグナルは、指定されたシグナルを ブロックしないようにシグナルマスクが変更されると送出されるかもしれません。 (しかし、保留されたシグナルがキューに入れられるかどうかはオペレーティング システムに依存します。)

マルチスレッドの環境では、スレッド毎に独自のシグナルマスクを持ちます。

Function: sys-sigmask how mask

現在のスレッドのシグナルマスクを変更し、以前のシグナルマスクを返します。 maskには新しいマスクを指定する<sys-sigset>オブジェクトか、 あるいはマスクを変更せず現在のマスクを得るだけなら#fを渡します。

mask<sys-sigset>オブジェクトを渡した場合、 引数howは以下の整数定数のうちの1つでなければなりません。

SIG_SETMASK

maskをそのスレッドのシグナルマスクとしてセットします。

SIG_BLOCK

そのスレッドのシグナルマスクにmaskにあるシグナルを追加します。

SIG_UNBLOCK

そのスレッドのシグナルマスクからmaskにあるシグナルを削除します。

Function: sys-sigsuspend mask

アトミックに、スレッドのシグナルマスクをmaskにセットし、 呼び出しているスレッドを一時停止します。ブロックされておらずシグナル ハンドラがインストールされているシグナルが送出されると、関連 付けられたハンドラが呼ばれ、sys-sigsuspendは戻ります。

Function: sys-sigwait mask

[POSIX] mask<sys-sigset>オブジェクトでなければなりません。 アトミックに、保留されたシグナルからmaskにあるシグナルの1つを クリアし、クリアしたシグナルの番号を返します。maskにある シグナルが1つも保留されていなければ、sys-sigwaitはシグナルが 届くまでブロックします。

sys-sigwaitを呼ぶ前に、maskにある全てのシグナルを、 全スレッドからブロックしておく必要があります。シグナルをブロックして いないスレッドがある場合、sys-sigwaitの動作は未定義です。

註:sys-sigwaitはシステムのsigwait関数を呼び出しますが、 この関数は待つべきシグナルにシグナルハンドラが設定されていた場合の 振る舞いが未定義となっています。困ったことになるのを避けるために、 sys-sigwaitはまずmaskに含まれるシグナルに ハンドラが設定されていたらそれをSIG_DFLにリセットしてから sigwaitを呼び出し、それが戻った後でハンドラを元に戻します。 sys-sigwaitが待っている間に他のスレッドでシグナルハンドラを 変更してはいけません。そうした場合の動作は不定です。


6.24.7.5 シグナルとスレッド

シグナルのセマンティクスはマルチスレッド環境では少々複雑に見えます。 しかし、いくつかのルールを覚えてしまえば、とても理解しやすいものでも あります。さらにGaucheでは、プログラマの簡単に使えるようにデフォルトの 振る舞いをセットアップしています。

細かいことは知りたくないという場合は、 次の1つのことだけを覚えておいて下さい。 デフォルトでは、シグナルはメインスレッドで処理されます。 しかし、メインスレッドがmutexや条件変数で一時停止している場合は、 シグナルは全く処理されないので注意が必要です。

詳細に興味がある場合は、ここにルールがあります。

  • シグナルハンドラのセッティングは、全てのスレッドで共有されます。
  • シグナルマスクはスレッド固有です。
  • プロセスが非同期のシグナルを受け取ったら(他のプロセスからシグナルが 送出されたと考えて下さい)、そのシグナルをブロックしていないスレッドの うちから任意の1つのスレッドが選ばれます。
  • シグナルハンドラは選択されたスレッドにおいて実行されます。 しかし、選択されたスレッドがmutexのロックの獲得や条件変数を待っている 場合は、シグナルの処理はそのスレッドが再開するまで遅延されます。 シグナルの送出自体はスレッドを再開しません。

これらのルールにはいくつかの暗黙の了解があります。

特定のシグナルをブロックしないスレッドが1つ以上ある場合、 どのスレッドがそのシグナルを受け取るかを知る術はありません。 そのような状況は、GaucheにおいてはCプログラムよりもさらに不便です。 なぜなら、受信側のスレッドがmutexや条件変数で待機している場合、 シグナル処理は無期限に遅延されうるからです。 したがって、それぞれのシグナルについて、それを受け取ることのできるスレッドが 常にただの1つしかないようにすることを推奨します。

Gaucheでは、make-thread(スレッド手続き参照) で作られた全てのスレッドは、デフォルトで全てのシグナル(予約済みを除く) をブロックします。これは、全てのシグナルがメインスレッドへ 送られるということです。

もう1つの戦略は、シグナル処理のみを行うスレッドを作る方法です。

もしシステムがsys-sigwaitをサポートしていれば、ハンドル したい全てのシグナルを全てのスレッドでブロックしておき、シグナル 処理専用のスレッドでsys-sigwaitを呼び出してシグナルの 受信を待つことができます。sys-sigwaitの返り値がシグナル番号 なので、その値でディスパッチしてください。この方法ではシグナル ハンドラが呼び出されることはありません。

sys-sigwaitを使わないのであれば、メインスレッドでシグナルを ブロックして、シグナル処理専用スレッドを作り、そのスレッドで全ての シグナルを受け付けることができます。そのようなスレッドはsys-pause で単にループしていれば良いでしょう。sys-pauseがシグナルで中断 されると、シグナルハンドラがシグナル処理専用スレッドで呼び出されます。

(thread-start!
  (make-thread
    (lambda ()
      (sys-sigmask SIG_SETMASK (make <sys-sigset>)) ;;empty mask
      (let loop () (sys-pause) (loop)))))

複雑なアプリケーションでは、正確にスレッド毎のシグナル処理を 制御したいかもしれません。それは、いつでも、指定されたスレッドのみが 望むシグナルをブロックしないようにすれば、可能です。


6.24.8 システムへの問い合わせ

Function: sys-uname

[POSIX] 次の5要素のリストを返します。 (sysname nodename release version machine)

Function: sys-gethostname

ホスト名を返します。システムでgethostname()が使えない場合、 sys-unameが返すリストの2番目の要素が使われます。

Function: sys-getdomainname

ドメイン名を返します。システムでgetdomainname()が使えない場合、 "localdomain"が返されます。

Function: sys-getcwd

[POSIX] 現在の作業ディレクトリを文字列で返します。 システムから現在の作業ディレクトリが得られない場合は、エラーが通知されます。 sys-chdir(他のファイル操作参照)、current-directory (ディレクトリユーティリティ参照)も参照して下さい。

Function: sys-getgid
Function: sys-getegid

[POSIX] 現在のプロセスの実グループIDと実効グループIDをそれぞれ整数で返します。 返されたグループIDからグループ名その他の情報を得るには sys-gid->group-namesys-getgrgidを使って下さい (Unixのグループとユーザ参照)。

Function: sys-setgid gid

[POSIX] 現在のプロセスの実効グループIDをセットします。

Function: sys-getuid
Function: sys-geteuid

[POSIX] 現在のプロセスの実ユーザIDと実効ユーザIDをそれぞれ整数で返します。 返されたユーザIDからユーザ名その他の情報を得るには sys-uid->user-namesys-getpwuidを使って下さい (Unixのグループとユーザ参照)。

Function: sys-setuid uid

[POSIX] 現在のプロセスの実効ユーザIDをセットします。

Function: sys-setugid?

プロセスがsuid/sgidされていたら#tを、そうでなければ#fを返します。

註:プラットフォームがissetugid()を持っていればそれを呼びます。 そうでない場合は、初期化時に実uid/gidと実効uid/gidが異なるかどうかを 記録しています。(後者の場合、Gaucheが組み込みSchemeエンジンとして使われていて、 プロセスがGauche初期化前に[e]uid/[e]gidを変更していたケースは検出できないことに 留意してください)。

Function: sys-getgroups

[POSIX] 補助的なグループのIDの整数のリストを返します。

Function: sys-setgroups gids

現在のプロセスのグループIDのリストを、 引数gidsで与えたグループIDのリストに置き換えます。 呼び出すプロセスは適切な特権を持っていなければなりません。

この手続きは、機能識別子gauche.sys.setgroupsがあるときのみ 使えます。ポータブルなコードではcond-expandを用いてください。

(cond-expand
  [gauche.sys.setgroups (sys-setgroups '(0 1))]
  [else])
Function: sys-getlogin

[POSIX] 現在のプロセスの制御端末にログインしているユーザの名前を文字列で 返します。システムがその情報を決定できない場合、#fが返されます。

Function: sys-getpgrp

[POSIX] 現在のプロセスのプロセスグループIDを返します。

Function: sys-getpgid pid

pidで指定されたプロセスのプロセスグループIDを返します。 pidが0の場合、現在のプロセスが使われます。

getpgid()はPOSIXではないことに注意して下さい。 システムにgetpgid()がない場合、pidが0ならば sys-getpgidがまだ動作しますが(それは単にsys-getpgrpを呼びます) 、pidが0でない場合はエラーが通知されます。

Function: sys-setpgid pid pgid

[POSIX] プロセスpidのプロセスグループIDをpgidにセットします。 pidが0ならば、現在のプロセスのプロセスIDが使われます。 pgidが0ならば、pidで指定されたプロセスのプロセスIDが 使われます。 (したがって、sys-getpgid(0, 0)は、現在のプロセスのプロセス グループIDを現在のプロセスIDにセットします。)

Function: sys-setsid

[POSIX] 呼んでいるプロセスがプロセスグループリーダでなければ、 新しいセッションを作ります。

Function: sys-getpid
Function: sys-getppid

[POSIX] 現在のプロセスIDと親プロセスのIDをそれぞれ返します。

Function: sys-times

[POSIX]

Function: sys-ctermid

[POSIX] プロセスの制御端末の名前を返します。 これは単に``/dev/tty''かもしれません。sys-ttynameも参照して下さい。

Function: sys-getrlimit resource
Function: sys-setrlimit resource current :optional maximum

[POSIX] プロセスのリソースリミットを取得あるいは設定します。 resourceはリソースの種類を指定する整数値です。 以下にリストする定数が定義されています。 (bsdlinuxとマークされている値は、POSIXでは 定義されていないけれどBSDもしくはLinuxで定義されていることを示します。 他のプラットフォームでそれらが定義されているかどうかは、 該当システムのgetrlimitのマニュアルを参照してください。)

RLIMIT_AS                      RLIMIT_CORE
RLIMIT_CPU                     RLIMIT_DATA
RLIMIT_FSIZE                   RLIMIT_LOCKS
RLIMIT_MEMLOCK (bsd/linux)     RLIMIT_MSGQUEUE (linux)
RLIMIT_NICE (linux)            RLIMIT_NOFILE
RLIMIT_NPROC (bsd/linux)       RLIMIT_RSS (bsd/linux)
RLIMIT_RTPRIO (linux)          RLIMIT_SIGPENDING (linux)
RLIMIT_SBSIZE                  RLIMIT_STACK
RLIMIT_OFILE
Function: sys-nice inc

[POSIX] 現在のプロセスのnice値にincを加算します。incは正確な整数でなければなりません。 ルートユーザのみがincに負の値を指定できます。 新たなnice値を返します。

Function: sys-strerror errno

errnoはシステムエラー番号を表現する非負正確整数でなければなりま せん。この関数はエラーを説明する文字列を返します。

ポータブルなコードには、SRFI-238のコードセットを使うこともできます (srfi.238 - コードセット参照)。

errnoを表現するのに、以下の定義済み定数が使えます。各定数はシス テムエラーを表現する非負正確整数に束縛されています。実際の値はシステム ごとに違い、またシステムによっては定義されていない定数があるということ に注意してください。

E2BIG             EHOSTDOWN         ENETDOWN          ENXIO
EACCES            EHOSTUNREACH      ENETRESET         EOPNOTSUPP
EADDRINUSE        EIDRM             ENETUNREACH       EOVERFLOW
EADDRNOTAVAIL     EILSEQ            ENFILE            EPERM
EADV              EINPROGRESS       ENOANO            EPFNOSUPPORT
EAFNOSUPPORT      EINTR             ENOBUFS           EPIPE
EAGAIN            EINVAL            ENOCSI            EPROTO
EALREADY          EIO               ENODATA           EPROTONOSUPPORT
EBADE             EISCONN           ENODEV            EPROTOTYPE
EBADF             EISDIR            ENOENT            ERANGE
EBADFD            EISNAM            ENOEXEC           EREMCHG
EBADMSG           EKEYEXPIRED       ENOKEY            EREMOTE
EBADR             EKEYREJECTED      ENOLCK            EREMOTEIO
EBADRQC           EKEYREVOKED       ENOLINK           ERESTART
EBADSLT           EL2HLT            ENOMEDIUM         EROFS
EBFONT            EL2NSYNC          ENOMEM            ESHUTDOWN
EBUSY             EL3HLT            ENOMSG            ESOCKTNOSUPPORT
ECANCELED         EL3RST            ENONET            ESPIPE
ECHILD            ELIBACC           ENOPKG            ESRCH
ECHRNG            ELIBBAD           ENOPROTOOPT       ESRMNT
ECOMM             ELIBEXEC          ENOSPC            ESTALE
ECONNABORTED      ELIBMAX           ENOSR             ESTRPIPE
ECONNREFUSED      ELIBSCN           ENOSTR            ETIME
ECONNRESET        ELNRNG            ENOSYS            ETIMEDOUT
EDEADLK           ELOOP             ENOTBLK           ETOOMANYREFS
EDEADLOCK         EMEDIUMTYPE       ENOTCONN          ETXTBSY
EDESTADDRREQ      EMFILE            ENOTDIR           EUCLEAN
EDOM              EMLINK            ENOTEMPTY         EUNATCH
EDOTDOT           EMSGSIZE          ENOTNAM           EUSERS
EDQUOT            EMULTIHOP         ENOTSOCK          EWOULDBLOCK
EEXIST            ENAMETOOLONG      ENOTTY            EXDEV
EFAULT            ENAVAIL           ENOTUNIQ          EXFULL
EFBIG
Function: sys-errno->symbol k
Function: sys-symbol->errno symbol

これらの手続きは、整数のエラー番号と、Unixでのエラー名を表すシンボル(例:EINTR)とを 相互に変換します。

与えられたエラー番号もしくはエラー名が実行中のプラットフォームで有効でない場合は #fが返されます。使えるかもしれないエラー名については上のsys-strerror の項を参照してください。

有効なエラー名およびその整数値はプラットフォーム毎に異なります。 これらの手続きは、システムエラーを扱うメタなコードをポータブルに書く時に役立つでしょう。

ポータブルなコードには、SRFI-238のコードセットを使うこともできます (srfi.238 - コードセット参照)。


6.24.9 時間

Gaucheでは時間は2種類の表現を持ちます。ひとつはPOSIX APIとコンパチブルな 表現で、もう一つはSRFI-18、SRFI-19、SRFI-21とコンパチブルな表現です。 多くの手続きはどちらの表現も理解しますが、そうでない場合は 適用可能な表現を’POSIX time’または’SRFI time’と表記します。

POSIX timeは実数で、Unix Epoch(Jan 1, 1970, 0:00:00GMT)からの秒数で 表現されます。POSIXのtime(2)に対応するsys-time手続きは この表現を返します。

SRFI互換の時間は<time>クラスのインスタンスとして表現され、 秒、およびナノ秒のスロットを持ちます。 また、時間の種別(UTC、TAI、期間、プロセス時間、他)も保持しています。 Current-timeはこの表現を返します。

POSIX time

Function: sys-time

[POSIX] 現在の時間を POSIX 時間(エポック(00:00:00 UTC, January 1, 1970) からの秒数)で返します。マシンのアーキテクチャによっては、非正確数で あるかもしれません。

Function: sys-gettimeofday

2つの値を返します。1970/1/1 0:00:00 UTC を基準として、 1つ目の値は秒数、2つ目の値は端数をマイクロ秒で表したものです。 システムが gettimeofday 呼び出しをサポートしていない場合、 この手続きは time() を呼び出し、その場合はマイクロ秒の 部分はいつも 0 です。

Builtin Class: <sys-tm>

カレンダーである、struct tm を表します。以下のスロットを持ちます。

Instance Variable of <sys-tm>: sec

秒。0-61。

Instance Variable of <sys-tm>: min

分。0-59。

Instance Variable of <sys-tm>: hour

時。0-23。

Instance Variable of <sys-tm>: mday

月の日。1 から数える。1-31。

Instance Variable of <sys-tm>: mon

月。0 から数える。0-11。

Instance Variable of <sys-tm>: year

1900年からの年数。例えば、102 なら 2002年。

Instance Variable of <sys-tm>: wday

曜日。日曜は 0 .. 土曜は 6。

Instance Variable of <sys-tm>: yday

1年の中での日数。1月1日は 0 .. 12月31日は 364 か 365。

Instance Variable of <sys-tm>: isdst

夏時間が有効であるかどうかを指定するフラグ。有効なら正の数、無効なら 0、 分からなければ負の数。

Function: sys-gmtime time
Function: sys-localtime time

[POSIX] time<sys-tm> オブジェクトに変換します。 標準時での表現かローカルタイムゾーンでの表現かで使い分けます。 Time は POSIX 時間か SRFI 時間です。

Function: sys-ctime time

[POSIX] time を POSIX の ctime() を使って文字列表現に変換します。 Time は POSIX 時間か SRFI 時間です。

Function: sys-difftime time1 time0

[POSIX] 2つの時間の差を、秒の実数で返します。Time0time1 は POSIX 時間か SRFI 時間です。

Function: sys-asctime tm

[POSIX] <sys-tm> オブジェクトである tm を文字列表現に変換します。

Function: sys-strftime format tm

[POSIX] <sys-tm> オブジェクトである tm を、フォーマット文字列 format に従って文字列表現に変換します。 formatの書き方はシステムのstrftimeのマニュアルエントリを参照してください。

フォーマット結果が異常に長い文字列になる場合は、空文字列が返されることがあります。

Function: sys-mktime tm

[POSIX] ローカルタイムとして表現された <sys-tm> オブジェクトである tm を POSIX 時間(エポックからの秒数)に変換します。

Function: sys-tm->alist tm

Deprecated.

SRFI time

Builtin Class: <time>

ある時刻を表す<time>オブジェクトです。

Instance Variable of <time>: type

timeの型を表します。デフォルトはtime-utcで、Unixエポックからの 秒数を表します。SRFI-19(srfi.19 - 時間のデータ型と手続き参照) ではさらに型が追加されています。

Instance Variable of <time>: second

timeの秒の部分です。

Instance Variable of <time>: nanosecond

timeのナノ秒の部分です。

Function: current-time

[SRFI-18][SRFI-21] 現在の時間をtime-utcで表す<time>オブジェクトを返します。 srfi.19 - 時間のデータ型と手続きでは、current-timeが再定義され、 timeの型を指定するオプショナル引数を受け付けるようにされています。

Function: time? obj

[SRFI-18][SRFI-19][SRFI-21] objがtimeオブジェクトなら#tを返します。

Function: absolute-time obj :optional current-time

引数は<time>オブジェクト、実数、もしくは#fでなければなりません。 絶対時刻を表す<time>オブジェクトの場合は絶対時刻を、 time-duration型の<time>オブジェクトの場合は現在時刻からの相対時間を、 実数の場合は現在時刻からの相対秒数を示します。

この手続きは、引数が#fなら#fを、そうでなければ 絶対時刻に変換したUTC <time>オブジェクトを返します。

timeout引数を取る多くの手続きが、同じ形式の引数を取ります。 この手続きはそれらと同様に時刻を扱うのに便利です。

省略可能なcurrent-timeオブジェクトは、もし与えられたなら 絶対時刻の<time>オブジェクトか#fでなければなりません。 <time>オブジェクトの場合は、実際の現在時刻のかわりに それが現在時刻として使われます。

Function: seconds+ time x

[SRFI-226+] 与えられたtimeよりx秒後を表すtimeオブジェクトを作って返します。 返されるtimeオブジェクトの型はtimeと同じです。 xは有限の実数です。xが負の場合は、与えられた時間より前の時間が返ります。

この手続きはSRFI-226準拠のコードを書くために用意されています。 Gauche専用のコードなら上のabsolute-timeも使えます。

時間の計算には、SRFI-19のadd-duration/subtract-duration も使えます。時間に関する手続きを参照してください。

Function: time->seconds time
Function: seconds->time seconds

[SRFI-18][SRFI-21] timeオブジェクトと秒数(POSIX時間)を変換します。 time->secondsの引数timeは、<time>オブジェクトで なければなりません。


6.24.10 プロセス管理

以下の手続きは、システムコールに対する直接的なインタフェースを提供します。 gauche.process - 高レベルプロセスインタフェースも合わせて参照して下さい。 より高レベルの便利な手続きが定義されています。

Fork and exec

Function: sys-system command

[POSIX] サブプロセスで文字列commandを実行します。commandは通常、 shへ渡されるので、シェルのメタキャラクタは解釈されます。

OSがサブシェル実行に失敗した場合は、<system-error>エラーが投げられます。 そうでなければ、この手続きはサブシェルが終了するまで待ち、サブシェルの 終了ステータス(termination status)を整数で返します。

終了ステータスはsys-waitの戻り値と同じように解釈できます。 例えば、exit statusを取るにはまず戻り値をsys-wait-exited?で検査して、 それからsys-wait-exit-statusを適用します。

一般的に、sys-systemの戻り値をきちんと解析するのは面倒です。 というのも、ゼロでない場合、それはサブシェル本体の異常終了もしくはシグナルによる終了 を表しているかもしれないし、commandの異常終了もしくはシグナルによる終了 を表しているかもしれないからです。 サブプロセスの終了コードを精査する必要がある場合は、 gauche.processモジュールのdo-process等を使うことを推奨します (gauche.process - 高レベルプロセスインタフェース参照)。

Windowsネイティブな環境では、引数はcmd.exeに渡されます。 外部から供給された文字列を引数にしてcmd.exeを呼び出すことは 避けてください。Windowsのcmd.exeに渡す任意の文字列を安全にエスケープすることは 事実上不可能です。

Function: sys-fork

[POSIX] 現在のプロセスをフォークします。子プロセスにいるならば0が返り、 親プロセスにいるならば子プロセスのプロセスIDが返ります。 全ての開かれているファイルディスクリプタは、親プロセスと子プロセスで 共有されます。詳細は、システムのfork(2)を参照して下さい。

子プロセスがsys-execを呼ぶ代わりにSchemeコードを実行して 終了する場合は、exitではなくsys-exitを呼ぶ必要があります。 通常のexitの呼び出しはファイルバッファのフラッシュを試み、 OSによっては親のファイルバッファを混乱させるでしょう。

sys-forkは複数のスレッドが走っている時には安全ではないことに 注意してください。fork(2)システムコールはプロセスのメモリイメージを 複製しますが、それには他のスレッドでロックされているmutexも含まれます。 もしsys-forkの瞬間に他のスレッドが何かをロックしていたとすれば、 子プロセスでもその資源はロックされたままになりますが、 その時子プロセスはもはやその資源をアンロックするスレッドを持っていません。 (これは内部で使っているmutexにも起こり得るため、Schemeレベルでmutexを 全く使っていないとしても防ぐことはできません)。

やりたいことが、マルチスレッドアプリケーションで別プログラムをspawnする ことであるなら、下に説明するsys-fork-and-execを使ってください。 どうしても別プロセスでSchemeコードを走らせたいのなら、よくある方法は、 アプリケーションの起動後すぐにマネージャプロセスとなる子プロセスをfork しておき、新たなプロセスが欲しくなったらそのマネージャプロセスに forkを依頼するという方法です。

Windowsネイティブな環境ではこの手続きは使えません。

Function: sys-exec command args :key directory iomap sigmask environment

[POSIX+] commandを引数のリストであるargsを伴って実行します。 現在のプロセスイメージはcommandに置き換えられるので、 この関数は戻りません。

argsの全ての要素は文字列でなければなりません。 argsの最初の要素は、argv[0]、すなわちプログラム名として 使われます。

(註: Windowsでは、sys-execsys-fork-and-execで バッチファイル(*.bat, *.cmd)を起動することもできます。 ただその場合、コマンドライン引数に文字()%!^<>&|"のいずれかを含めることは できません。これらの文字を安全にエスケープする包括的な方法が無いからです。 実行可能ファイルを直接指定する場合はこの制限はありません。)

キーワード引数directoryは文字列によるディレクトリ名 か#fでなければなりません。 文字列だった場合、sys-execはプログラムを実行する前に カレントワーキングディレクトリを指定ディレクトリに移動します。

キーワード引数のiomapは、与えられた場合は、開かれている ファイルディスクリプタがどのように扱われるかを指定します。 この引数は以下のフォーマットでなければなりません。

((to-fd . from-port-or-fd) ...)

to-fdは整数でなければならず、from-port-or-fdは整数のファイル ディスクリプタかポートでなければなりません。 リストのそれぞれの要素は、現在のプロセスのfrom-port-or-fdの ファイルディスクリプタを、実行されているプロセスのファイルディスクリプタ to-fdにマップさせます。

iomapが与えられると、iomapリストで指定されていないいかなるファイル ディスクリプタもexec()の前に閉じられます。さもなければ、現在のプロセスの 全てのファイルディスクリプタは開かれたままになります。

(sys-exec "ls" '("ls" "-l")) ⇒ ;; ls is executed.

(let ((out (open-output-file "ls.out")))
  (sys-exec "ls" '("ls" "-l") :iomap `((2 . 1) (1 . ,out)))
   ⇒
  ;; ls is executed, with its stderr redirected
  ;; to the current process's stdout, and its
  ;; stdout redirected to the file "ls.out".

sigmaskキーワード引数には、<sys-sigset>のインスタンスか #fを渡すことができます (シグナルマスクについてはシグナルを 参照して下さい)。<sys-sigset>のインスタンスを渡した場合、 この関数を呼び出したスレッドのシグナルマスクが、exec(2)を呼ぶ 直前にそれによって置き換えられます。 これは、全てのシグナルをブロックしているスレッドから外部プログラムを走らせる ような場合に便利です (シグナルとスレッドで述べるように、 新たなスレッドは全てのシグナルをデフォルトでブロックします)。 このような場合にsigmaskを設定しないと、execされたプロセスは スレッドのシグナルマスクを継承し、ほとんどのシグナルを受け付けないプロセスと なってしまうからです。通常、それはあまり便利ではありません。

最後に、environmentキーワード引数は新たなプロセスから見える環境を指定します。 デフォルト値は#fで、その場合は新たなプロセスは現在のプロセスの環境を引き継ぎます。 そうでなければ、引数は文字列のリストでなければならず、 各文字列は"NAME=VALUE"の形式でなければなりません。 NAMEが環境変数の名前を、VALUEがその値を示します。 NAME=を含むことはできませんが、VALUE=を含めることは できます。 この形式はsys-environが返す形式と互換です (環境の問い合わせ参照)。 したがって、sys-environで取得した環境にエントリを追加したり、 そこからエントリを削除したりしてこの引数に渡すことができます。

sys-execがエラーに遭遇すると、たいていの場合エラー条件を投げます。 しかし一旦ファイルディスクリプタの順番が変えられると、合理的な方法でエラーを処理する ことは実行不可能です(標準エラーがまだ有効かどうかさえ知る術がありません)。 したがって、その場合はGaucheはエラー時には単に終了するだけです。

Windowsネイティブ環境では、標準入力、標準出力、標準エラー出力に 関するリダイレクションのみが処理されます。Windowsはプロセス間通信としての シグナルをサポートしないので、シグナルマスクは無視されます。

Function: sys-fork-and-exec command args :key directory iomap sigmask detached environment

sys-execと同じですが、ファイルディスクリプタとシグナルマスクを変更して execvp(2)を実行する直前に、fork(2)を実行します。 子プロセスのプロセスidを返します。引数の意味はsys-execと同じです。

他のスレッドが走っている環境下で別プログラムをspawnしたい場合は、 sys-forksys-execを別々に使うのではなく、 この手続きを使ってください。 この手続き中では、fork(2)execvp(2)の間で メモリアロケーションもロックの獲得も行われないため、 マルチスレッド環境で実行しても安全になっています。

Windowsネイティブ環境では、この手続きはプロセスIDではなく 作られたプロセスに対するWindowsのハンドルオブジェクト (<win:handle>) を返します。Windowsプロセスハンドル 特有の手続きについては後に述べます。

また、sys-exec同様、Windowsネイティブ環境では、標準入力、標準出力、標準エラー出力に 関するリダイレクションのみが処理されます。

detachedキーワード引数に真の値が与えられた場合、 実行されるプロセスは現在のプロセスグループからは切り離されます。 つまり、現在のプロセスグループに送られるシグナルを、新しいプロセスは受け取りません。 この動作はデーモンプロセスを作る際の標準的な手順のひとつです。

Unixでは、実行されるプロセスがsetsid(2)を呼んで 独自のセッションを作るだけでなく、余分なfork(2) を実行することで親をinitプロセス (pid=1) に切り替えます。 (つまり、実行されるプロセスは実は呼び出すプロセスの孫にあたります。 親子関係はなくなりますが。返されるpidは実際に走っているこのプロセスのもので、 すぐに終了する中間プロセスのものではありません。)

Windowsネイティブ環境では、このフラグがあると プロセス作成時にCREATE_NEW_PROCESS_GROUPフラグが使われます。

Wait

Function: sys-wait

[POSIX] システムのwait(2)を呼びます。プロセスは、子プロセスの1つが 終了するまでその実行を一時停止します。2つの正確整数、1つ目は子プロセスのID、 2つ目はステータスコードを返します。ステータスコードは以下の関数によって 解釈できます。

Function: sys-waitpid pid :key nohang untraced

[POSIX] これは、waitの拡張バージョンである、waitpid(3)への インターフェースです。

pidは、待つべき子プロセスを指定する正確な整数です。正の整数ならば、 特定の子プロセスを待ちます。0ならば、このプロセスグループのいずれかの メンバを待ちます。-1ならば、いずれかの子プロセスを待ちます。 -1よりも小さければ、プロセスグループIDがpidの絶対値と等しいいずれかの 子プロセスを待ちます。

待つべき子プロセスが存在しない場合や、pidに具体的なプロセスIDが 与えられたがそれが現在のプロセスの子プロセスでない場合は エラー(<system-error>, ECHILD)となります。

キーワード引数nohangに真値が指定されていなければ、 呼んでいるプロセスは、それらの子プロセスのうちの1つが終了するまで一時停止します。

キーワード引数untracedに真値が指定されていれば、 停止した子プロセスのステータスも返ります。

戻り値は2つの正確整数で、1つ目は子プロセスのID、2つ目はステータスコードです。 nohangが真で子プロセスのステータスが利用できない場合は、1つ目の値は0です。

Windowsネイティブ環境では、この関数はpidにWindowsプロセスハンドル (<win:handle>)オブジェクトを受け取ることもできます。 その場合はそのハンドルの指すプロセスの終了を待ちます。 また、-1を渡していずれかの子プロセスの終了を待つこともできますが、 特定のプロセスグループの中の子プロセスを待つことはできません。

Function: sys-wait-exited? status
Function: sys-wait-exit-status status

[POSIX] 引数はsys-waitsys-waitpidの2番目の値として返される 終了ステータスです。子プロセスが正常終了したら、sys-wait-exited?#tを返します。sys-wait-exit-statusは、子プロセスが exit(2)に渡した終了コードか、main()の戻り値を返します。

Function: sys-wait-signaled? status
Function: sys-wait-termsig status

[POSIX] 引数は、sys-waitsys-waitpidの2つ目の戻り値である終了ステータスです。 子プロセスが捕捉されないシグナルで終了した場合は、sys-wait-signaled?#tを返します。 sys-wait-termsigは、子プロセスを終了したシグナルの番号を返します。

Function: sys-wait-stopped? status
Function: sys-wait-stopsig status

[POSIX] 引数は、sys-waitpidの2つ目の戻り値である終了ステータスです。 子プロセスが停止されれば、sys-wait-stopped?#tを 返します。このステータスは、sys-waitpiduntraced引数に 真値を持っている場合にのみ捕捉されます。sys-wait-stopsigは 子プロセスを停止させたシグナルの番号を返します。

Windowsネイティブ環境では、終了コードはUnixのように構造化されておらず、 プロセスが自発的に終了したか強制的に終了させられたかを判断する一般的な方法は ありません。Gauche自身は他のプロセスをsys-killで 終了させる場合に終了コード#xff09を送り、上のsys-wait-* 手続きもそれに合わせてあります。従ってGaucheによって終了させられたプロセスでは sys-wait-signaled?でそのことを検出できる可能性が高いでしょう。 (Windows上のシグナルのサポートについてはシグナルを参照してください。) Windowsネイティブ環境では、sys-wait-stopped?が真を返すことは (今のところ)ありません。

Windows特有のユーティリティ

以下の手続きはWindowsのプロセスハンドルにアクセスするものです。 Windowsネイティブ環境でのみ提供されます。

Function: sys-win-process? obj

[Windows] objがWindowsプロセスハンドルの場合に#tを、それ以外では#fを 返します。

Function: sys-win-process-pid handle

[Windows] Windowsプロセスハンドルhandleが示すプロセスの、整数のpid値を 返します。handleが有効なWindowsプロセスハンドルでない場合はエラーが 通知されっす。

プロセスハンドルからプロセスIDを得るAPIはWindows XP SP1から提供されるように なりました。それ以前のWindowsでこの手続きを呼ぶと-1が返されます。


6.24.11 I/Oの多重化

select(2)へのインターフェース関数です。 これらのプリミティブの上に構築された高次元のインターフェースが 提供されています。gauche.selector - 簡単なディスパッチャを 参照して下さい。

Builtin Class: <sys-fdset>

ファイルディスクリプタの集合であるfd_setを表します。 makeメソッドによって、空のファイルディスクリプタの集合を作れます。

(make <sys-fdset>)
Function: sys-fdset elt …

elt …で指定されたファイルディスクリプタを持つ 新たな<sys-fdset>のインスタンスを作成して返します。 各eltは、ファイルディスクリプタを指定する整数、ポート、 もしくは<sys-fdset>のインスタンスでなければなりません。 最後の場合は、与えられたfdsetに含まれるディスクリプタが 新たなfdsetにコピーされます。

Function: sys-fdset-ref fdset port-or-fd
Function: sys-fdset-set! fdset port-or-fd flag

fdsetの特定のファイルディスクリプタビットを取得・セットできます。 port-or-fdは関連付けられたファイルディスクリプタを持っていないポートで、 sys-fdset-ref#fを返し、sys-fdset-set!fdsetを 変更しません。flagは真偽値でなければなりません。

下記のように、sys-fdset-refのジェネリックなセッタが使えます。

(set! (sys-fdset-ref fdset port-or-fd) flag)
  ≡ (sys-fdset-set! fdset port-or-fd flag)
Function: sys-fdset-copy! dest-fdset src-fdset

src-fdsetの内容をdest-fdsetにコピーします。 dest-fdsetを返します。

Function: sys-fdset-clear! fdset

fdsetの内容をクリアし、それ自身を返します。

Function: sys-fdset->list fdset
Function: list->sys-fdset fds

fdsetを整数のファイルディスクリプタのリストに変換し、またその逆を行います。 実際は、list->sys-fdset(lambda (fds) (apply sys-fdset fds)) のように動作するため、 整数のファイルディスクリプタ以外にポートや他のfdsetを与えることもできます。

Function: sys-fdset-max-fd fdset

fdsetにある最大のファイルディスクリプタ番号を返します。

Function: sys-select readfds writefds exceptfds :optional timeout
Function: sys-select! readfds writefds exceptfds :optional timeout

ステータスを変更するためにファイルディスクリプタの集合を待ちます。 readfdswritefdsexceptfdsは、注目するファイル ディスクリプタの集合を表す<fdset>オブジェクトです。 readfdsにあるファイルディスクリプタは、文字を読み込む準備が 出来たかどうかを検査するために監視されています。 writefdsにあるファイルディスクリプタはそこへ書き込むことができる ようになったか監視されています。exceptfdsにあるファイルディスクリプタは 例外のために監視されています。条件を監視する必要がない場合は、これらの引数の 1つ以上に#fを渡すことができます。

timeoutsys-selectが条件の変更を待つ最大の時間を指定します。 それは、マイクロ秒を表す実数か、1つ目が秒数で2つ目がマイクロ秒である 2つの整数からなるリストです。#fを渡すと、sys-selectは 永久に待ちます。

sys-selectは4つの値を返します。1つ目の値は、ステータスの変更を 検知したディスクリプタの数です。timeoutが経過したら0になるでしょう。 2、3、4番目の値は、それぞれ読み込み、書き出し、例外のステータスを変更 するディスクリプタの集合を含む<fdset>オブジェクトです。 readfdswritefdsexceptfdsのうちの1つ以上に#fを 渡すと、対応する戻り値は#fになります。

sys-select!の仲間は、それが渡された引数<fdset>を変更することを 除けば、sys-selectと同じように動作します。 sys-selectは、新しい<fdset>オブジェクトを作り、その 引数を変更しません。


6.24.12 ガベージコレクション

ガベージコレクタは必要になった時に自動的に走るので、普段気にする必要はないでしょう。 けれどももし気にする必要が出てきた時は、いくつか使える手続きがあります。

Function: gc

フルGCを起動します。GCの影響をなるべく排除したいコードがある場合、 その直前にこの手続きを呼ぶことで影響を減らせるかもしれません。

Function: gc-stat

GCに関する統計情報を返します。返り値はリストのリストで、 内側のリストはキーワードと対応する数値からなります。 現在、返されるキーワードは :total-heap-size:free-bytes:bytes-since-gc:total-bytesです。


6.24.13 メモリマッピング

Class: <memory-region>

マップされたメモリ領域を表すオブジェクトです。sys-mmapによって返され、 make-view-uvectorに渡してアクセスできます。以下の読み取り専用スロットを 持っています。

Instance Variable of <memory-region>: address

マッピングされたアドレス。Schemeの世界では意味がありませんが、 外部関数に渡すことはできます。

Instance Variable of <memory-region>: size

マッピングの大きさをバイト数で。

Instance Variable of <memory-region>: protection

メモリ保護属性のビットマスク。整数定数 PROT_READPROT_WRITEPROT_EXECPROT_NONE の組み合わせのbitwise orです。詳しくは下のsys-mmapを参照。

Instance Variable of <memory-region>: flags

sys-mmapに渡されたフラグ。下のsys-mmapを参照。

Function: sys-mmap port prot flags size :optional offset

[POSIX] mmap(2) (WindowsではMapViewOfFileEx) を使って ファイルをメモリにマップします。マップされたメモリは <memory-region>オブジェクトとして返され、 make-view-uvectorでアクセスできます。

port引数はポートか#fでなければならず、ポートの場合は ファイルと結びつけられていなければなりません。この引数が#fの場合は、 ファイルの裏打ちがない「匿名の」メモリ領域がマップされます。この場合、 flags引数にMAP_ANONYMOUSが指定されていなければなりません。

port引数はメモリ領域の保護属性を指定します。以下の定数のbitwise or でなければなりません。

PROT_EXEC

メモリページに実行可能属性を付加。

PROT_READ

メモリページに読み取り可能属性を付加。

PROT_WRITE

メモリページに書き込み可能属性を付加。

PROT_NONE

ページにはアクセスできない。

flags引数は、以下の定数のbitwise orでなければなりません。

MAP_SHARED

マッピングはプロセス間で共有される。マップされたページを変更した場合、 その変更は同じ領域をマップしている他のプロセスからも見える。

MAP_PRIVATE

マッピングはプロセスだけに止まる。マップされたページを変更しても、 それは外からは見えない。

MAP_ANONYMOUS

マップされたページはファイルに結びつけられない。

sizeは正の正確な整数、offsetは非負の正確な整数でなければなりません。 それらはファイル中のマップすべき領域を指定します。offsetバイト目から始まる、 sizeバイトの領域です。offsetはページサイズの倍数でなければならず、 省略された場合は0となります。マッピングがファイルと結びつけられていない場合 (port#fの場合)、offsetは無視されます。

マップされたメモリを陽にunmapする必要はありません。 <memory-region>オブジェクトがガベージコレクトされる時に、メモリはunmapされます。

Function: make-view-uvector mem class length :optional offset immutable?

この手続きはメモリ領域memの「窓」になるユニフォームベクタを作って返します。 mem<memory-region>オブジェクトでなければなりません。 マップされているメモリ領域に変化があれば、uvectorの内容も変化します。 メモリが書き込み可能でマップされていれば、uvectorを変更するとそれが メモリにも反映されます。

classはユニフォームベクタのクラスでなければなりません (例: <u8vector>)。 lengthは作られるユニフォームベクタの長さ(要素数)です。 メモリはネイティブバイトオーダーでアクセスされます。length#fでも良く、 その場合はメモリ領域の最後までが使われます。

offset引数はメモリ領域先頭からのオフセットをバイト数で指定します。 これはユニフォームベクタの要素サイズの倍数でなければなりません。

メモリ領域が読み出し専用であれば(つまり、PROT_WRITE属性なしでマップされていれば)、 返されるユニフォームベクタは変更不可になります。そうでなければデフォルトで変更可能な ユニフォームベクタが返されますが、immutable?引数に真の値を与えることで、 変更不可なユニフォームベクタを得ることもできます。

メモリ領域は、それを参照しているユニフォームベクタが生きている限りは ガベージコレクトされません。


6.24.14 その他のシステムコール

Function: sys-pause

[POSIX] シグナルキャッチ関数の実行かプロセスの終了を指示するシグナルを 受け取るまでプロセスを一時停止します。この関数は、シグナルキャッチ関数が 戻ったときにのみ戻ります。戻り値は未定義です。

Schemeレベルでは、pause()を呼ぶだけでは上記のセマンティクスを 満足しません。内部的にこの手続きは現在のシグナルマスクを伴って、 sigsuspend()を呼びます。

Function: sys-alarm seconds

[POSIX] SIGALRMシグナルがseconds秒後に送出されるように準備します。 以前のアラームクロックのセッティングはキャンセルされます。 secondsに0を渡すと、新しいアラームをスケジューリングしません。 以前にスケジューリングされていたアラームが送出されるまでの残り時間を 秒数で返します(アラームがアクティブでない場合は0を返します)。

Function: sys-sleep seconds :optional (no-retry #f)

[POSIX] 指定された秒数が経過するまで、呼び出したスレッドを一時停止します。

libcのsleep(3)は、シグナルを受けると指定時間経過前であっても 戻ってきます。その場合sys-sleepはデフォルトで、(Schemeのシグナルハンドラが あればそれを呼び出した後)残り時間を引数にして再びsleep(3)を呼び出します。 従ってsys-sleepを呼び出したスレッドは、少なくとも指定した時間、 眠れることが保証されます。

もしsys-sleepがシグナルを受けた場合にすぐ戻ってきてほしければ、 省略可能引数no-retryに真の値を渡してください。

デフォルトでsleep(3)を再呼び出しする理由は、GaucheのGCが スレッド間同期にシグナルを使う場合があるからです。 もし一つのスレッドがsys-sleepで待っている間にもうひとつのスレッドが GCをトリガすると、sys-sleepが時間経過前に戻ってくる可能性があります。 他のスレッドがたくさんアロケートする場合、sys-sleepはすぐに 戻ってきてしまい、信頼できなくなるかもしれません。

指定時間が満了した場合(no-retryが偽であれば常にそうです)、 sys-sleepは0を返し、 シグナルによって一時停止が解除された場合は、満了までの秒数を返します。

POSIX実装間でポータブルにするためには、secondsを65536より小さく保って 下さい。

システムによってはsleep(3)の実装にalarm(2)を用いている可能性があるので、 sys-sleepsys-alarmを混ぜて使うことはおすすめしません。

Function: sys-nanosleep nanoseconds :optional (no-retry #f)

[POSIX] 指定されたナノ秒が経過するまで、呼び出したスレッドを一時停止します。 引数nanoseconds<time>オブジェクト(時間参照)か 実数です。

システムのnanosleep(2)は、シグナルを受けると指定時間経過前であっても 戻ってきますが、sys-nanosleepはデフォルトで、(Schemeのシグナルハンドラが あればそれを呼び出した後)残り時間を引数にして再びnanosleep(2)を呼び出します。 従ってsys-nanosleepを呼び出したスレッドは、少なくとも指定した時間、 眠れることが保証されます。

もしsys-nanosleepがシグナルを受けた場合にすぐ戻ってきてほしければ、 省略可能引数no-retryに真の値を渡してください。

デフォルトでnanosleep(2)を再呼び出しする理由は、GaucheのGCが スレッド間同期にシグナルを使う場合があるからです。 もし一つのスレッドがsys-nanosleepで待っている間にもうひとつのスレッドが GCをトリガすると、sys-nanosleepが時間経過前に戻ってくる可能性があります。 他のスレッドがたくさんアロケートする場合、sys-nanosleepはすぐに 戻ってきてしまい、信頼できなくなるかもしれません。

nanosecondsが経過した場合の返り値は#fです。 no-retryが偽であれば常にそうなります。 sys-nanosleepがシグナルによって割り込まれた場合は、 残りの時間を表す<time>オブジェクトを返します。

;wait for 0.5 sec
(sys-nanosleep 500000000)

;wait for 1.3 sec
(sys-nanosleep (make <time> :second 1 :nanosecond 300000000))

Windowsネイティブ環境では、この関数はSleepによってエミュレートされます。 引数はミリ秒の単位に切り上げられます。またシグナルによって中断されることはありません。

Function: sys-random
Function: sys-srandom seed

擬似的な乱数ジェネレータです。 sys-randomは0からrand_max(それ自体を含む)までの間で乱数を 返します。これはrandom(3)への直接的なインターフェースです。 システムにrandom(3)がない場合、lrand48(3)が使われます。

sys-srandomは乱数ジェネレータの種をセットします。 システムによって、srandom(3)srand48(3)を使います。

これらの関数の意図は、乱数ジェネレータ(RNG; random number generator)の 品質や速度を気にしないアプリケーションに、簡便なRNGを提供することです。 本格的な統計分析には、math.mt-randomモジュールのMersenne Twister RNGを 使って下さい(math.mt-random - Mersenne Twister乱数発生器参照)。

Variable: RAND_MAX

sys-randomが返す正の整数に束縛されます。

Function: sys-get-osfhandle port-or-fd

[Windows] この手続きはWindowsネイティブ版だけにあります。 与えられたポートまたは整数のファイルディスクリプタに対応する Windowsファイルハンドルを返します。引数がファイルハンドルに 対応していなかった場合はエラーが投げられます。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT