• ベストアンサー

リエントランスな関数

最近、リエントランス(re-entrance)な関数という言葉を聞きました。 恥ずかしながら、全然意識したことのない言葉でした。 C言語の標準ライブラリには、リエントランスな関数とそうでない関数があると聞いたのですが、それを調べるにはどのようにしたら良いでしょうか? ANSIの仕様で決まっているのでしょうか? それとも、コンパイラ依存なのでしょうか? 参考書とかHPとかを紹介していただけるとありがたいです。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

どちらかというと, 普通は reentrant な関数というような気はします (reentrant は形容詞, reentrance は名詞) が, ISO の仕様として C の標準ライブラリはどれもリエントラントであることが保証されません. 従って, 一般にシグナルハンドラで標準ライブラリを呼び出すことはできません (と, ちゃんと規格に書いてあります). もちろん処理系によってリエントラントであってもかまいませんが, リエントラントであることを前提としたプログラムは移植するときに問題となりえます.

okazaki0ko
質問者

お礼

再入可能であることは、保証されていないということですね。 その結果、割り込みでは使用してはいけない・・・と理解しました。 リエントラントが形容詞なら、それに「な(断定の助詞の連体形)」は付けることはできませんね。 リエントランスは名詞(体言)なので「な(断定の助詞の連体形)」は付けることができますが。 リエントランス関数とは言えないけど、リエントラント関数とは言えますね。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

処理系に依存するので, 特定の標準ライブラリ関数がリエントラントかどうかを調べるにはその処理系の資料を読むしかないです. まあ, 明らかにリエントラントでない標準ライブラリ関数はありますが. 念のためですが, 規格では 「標準ライブラリ関数がリエントラントであることを保証しない」 The functions in the standard library are not guaranteed to be reentrant つまり「リエントラントであってもいいしリエントラントでなくてもいい」であって, 「すべて非エントラント」であると規定しているわけではありません>#4... もちろんプログラムを書く上では (すべての関数がリエントラントでないことを想定しなければならないので) 実質的に同義ですが, そんな規定はだれにとっても困るだけ.

okazaki0ko
質問者

お礼

> 処理系に依存するので, 処理系依存のプログラムは書きたくないので、処理系依存の部分は排除したいと思います。 ただ、OSを設計(模倣)していますので、どうしてもマシン依存=処理系依存があるのですが、最低限に抑えたいのです。 >「標準ライブラリ関数がリエントラントであることを保証しない」 ということで、再入可能ではないことを前提に設計して行きたいと思います。 リエントランス・リエントラントについては、#2のお礼を見てください。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.5

追記。 ANo.4の回答では「fopenは非リエントラントな関数」と回答しましたが、実装を工夫し、以下のようにすれば「リエントラントな関数」になります。 ・システムコールでファイルを開く ・ファイルがオープン出来なければエラーで帰る ・割り込み禁止にする ・ファイル識別子の空きを探し、空きが無かったら、ファイルを閉じ、割り込み禁止解除をして、エラーで帰る ・空きがあったら、それを使用済みに書き替える ・割り込み禁止解除し、ファイル識別子のポインタを戻り値にして帰る これで「空きを探して、使用済みに変え、それを返す」までの間、他のスレッドや割り込み処理ルーチンに切り替わる心配はないので「リエントラントな関数」となります。 とは言え「使っているコンパイラのfopenが、こういう親切な実装をしてくれてるかどうかは、実際に実装した人にしか判らない」ので「使う側は、非リエントラントだと思って、安全な使い方をするしかない」のです。

okazaki0ko
質問者

お礼

OSの設計をしているので、OS依存の関数を使うことはないのですが、 > とは言え「使っているコンパイラのfopenが、こういう親切な実装をしてくれてるかどうかは、実際に実装した人にしか判らない」ので「使う側は、非リエントラントだと思って、安全な使い方をするしかない」のです。 この方針で行くことにしました。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.4

「リエントラント」ですね。 基本的には「その関数が終了して呼び出し元に復帰する前に、誰かが同じ関数を呼んだ場合、正常に動作するかどうか?」で「リエントラントな関数」か「リエントラントでない関数」かが決まります。 通常、静的メモリを操作しする関数は「リエントラントでない関数」と思って間違いありません。 例えば、fopenは、静的メモリに配置された「ファイル識別子」を返します。簡単に言えば「FILEへのポインタ」です。なので、fopenは「リエントラントでない関数」です。 fopenは、未使用のファイル識別子を探し、空きがあれば、システムコールでファイルを開き、開けたら、ファイル識別子を使用済みに書き替え、そのファイル識別子を返します。 この処理が「2つのスレッドで、ほぼ同時に起こった」としたら、どうなるでしょう? 1.スレッド1でfopenを呼んだ。 2.スレッド1は、静的メモリに配置された未使用のファイル識別子を探し、5番に空きがあったので、システムコールでファイルを開こうとした。 3.システムコールが呼ばれたので、スレッド2に切り替わった。 4.スレッド2でfopenを呼んだ。 5.スレッド2は、静的メモリに配置された未使用のファイル識別子を探し、5番に空きがあったので、システムコールでファイルを開こうとした。 6.システムコールが呼ばれたので、スレッド1に切り替わった。 7.スレッド1が呼んだfopen関数は、ファイルが開けたので、5番を使用済みにして、5番のファイル識別子を返した。 8.スレッド2に切り替わると、スレッド2が呼んだfopen関数は、ファイルが開けたので、5番を使用済みにして、5番のファイル識別子を返した。 このように、2つのスレッドのfopenで「同一のファイル識別子(上記の例では5番のファイル識別子)を返されてしまう」ので、動作が不安定になります。 本当であれば、fopenを呼んだ順に、5番、6番のファイル識別子が返されねばなりません。 で、仕様上は「C標準ライブラリ関数は、すべて非エントラント」ですが、処理系によっては、実装の際に「エントラントな関数」として実装される事もあり「事実上、エントラントか非エントラントかは、処理系に依存する」と言うのが現状です。

okazaki0ko
質問者

お礼

> 通常、静的メモリを操作しする関数は「リエントラントでない関数」と思って間違いありません。 この点がポイントになることは、解っていました。 さて、どの関数が静的領域をいじるのか? それを調べる方法は果たして存在するのか? 仕様で決められていれば楽なのに・・・。 と言った所です。 ですので、 > で、仕様上は「C標準ライブラリ関数は、すべて非エントラント」ですが、 で、解決です。 リエントランス・リエントラントについては、#2のお礼を見てください。

回答No.3

「リエントラント(再入可能)」な関数  とは、当該関数実行中に、他のスレッドなどからさらに実行が可能  な実装仕様を言います。一般にWindowsのコールバック関数及び一  群のメッセージ処理関数群はリエントラントであることが要求され  ていますが、そうでなくても再入しない場合がほとんどなので動い  ちゃいます(笑)。但し、DLLの関数はリエントラントであることが  より強く要求されます。  似たように言葉に「リカーシブ(再帰可能)」がありますが、こちら  の条件は当該関数から当該関数をコールしても動作することです。  ニーモニックレベルだと「リロケータブル」というのも良く言われ  ますが、特別に処理しない限り、C言語では全てリロケータブルに  翻訳されます。

okazaki0ko
質問者

お礼

今回は、OSの設計でぶつかった問題でした。 なので、パソコンのOS類のお世話にはならない訳ですが(組み込み系の設計です)、DLLが再入可能である必要があることは、良く解ります。 リロケータブルは、ちょっと今回の件とは関係ないような・・・。 リエントランス・リエントラントについては、#2のお礼を見てください。

  • eroermine
  • ベストアンサー率18% (83/444)
回答No.1

thread safe で検索すればわかると思います。 昔はリエントラントと言ってましたね。SUN4あたりからそういう用語が出てきたかと。 The GNU C library uses thread safe functions by default and libc5 used non thread safe versions. これはなんか gcc のlibcが遅いとか言う苦情にたいする反論。 コンパイラにオプションがあったりもします。 言語によってはリエントラント関数にはなにか特別な識別子があったりもします。 今思い出せない。 参考書よりも検索しまくりでどうぞ。

okazaki0ko
質問者

お礼

> thread safe で検索すればわかると思います。 > 参考書よりも検索しまくりでどうぞ。 検索用キーワードを教えていただいたので、検索かけてみます。

関連するQ&A