• ベストアンサー

非再入可能なプログラム

非再入可能なプログラムの意義がわかりません。 別にどのプログラムも再入可能にしておけばいいと思うのですが 非再入可能にする意味ってあるのでしょうか? 呼出したプログラムが、ちゃんと呼び出し元に戻らないと どんなプログラムでも困ると思うのですが。。

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

  • ベストアンサー
  • GOOD-Fr
  • ベストアンサー率32% (83/256)
回答No.8

いちおう、最初に言い訳。 汎用機は学生の時の「言語実習」で Pascal のプログラムを作らされた時に使ったことがあるだけなので、「まったく」詳しくありません。(そのときも、あまりのレスポンスの悪さに、自宅でデバッグまでしてからエディタで入力して課題を提出していました) ミニコンはクラブ保有のものがありましたが、「起動と停止がめんどくさい」ので、パソコン上で OS を使ってコンパイラやアセンブラを使っていました。(当時は、BASIC インタープリタを使うことが、プログラムだと信じられていましたが) さて、 「ただ、このバッチから呼ばれる共通ルーチン(アベンドルーチンなど)はどのモジュールから呼ばれることもあります」 アベンドは、Abnormal End ですね? OS レベルに近い、もしくは、OS 内部というのは、実はリエントラントになっていない部分が存在しています。OS はマルチタスク、マルチスレッドをサポートしていても、です。これは「プログラムがめんどくさいから」ではなくて「逐次処理されることを保証したいから」です。つまり、「同時に呼び出しても、必ずどちらかの処理を先に処理してから次の処理を実行する」というふうにさせたいわけです。 プログラマレベルでは「好きな時に呼び出してかまわないルーチン」のように見えますが、実際には逐次処理されることになります。(そのルーチンに飛び込む前にたとえばセマフォを獲得しないといけないように OS 内部を作っておく、セマフォを獲得できないときはそこでスリープして、先に入ったプログラムがルーチンを抜けてセマフォを解放すると、次のプログラムがセマフォを獲得してルーチンに突入できる、とか) このようなルーチンであれば、リエントラント可能に作る必要はありません。 もう一度簡単にまとめると、「プログラマからは同時呼び出し可能なルーチンに見えても、実際に内部構造がそうなっているとは限らない」となります。 OS のレスポンスを上げるためにはこういうプリミティブな「クリティカルセクション」をいかに少なくできるか、というところがあります。 ですから「変数域の上書きがされる可能性があると思ってよいのでしょうか?」という心配はしなくてもいいと思います。仕様書にしたがって呼び出せば、OS 側で「よしなにはかって」くれますよ。 追記 さきほど、ルーチンをリエントラントとしない理由として、「メモリの節約」をあげるのを忘れていました。仮想記憶があるとはいえ、汎用機では「潤沢なメモリ」を前提にプログラムを書くことはできないかもしれません。(この文章を書いているパソコンは 6GB のメモリを積んでいて、フリーメモリが 4GB 以上もありますし、最近プログラムしていても「とりあえず 4GB」はメモリがあると思っていてかまわないので、ついついメモリを節約することを失念していました)

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (10)

回答No.11

#10です。 #9の(2)を少し訂正。 (2)リユーザブル  ディスク上のライブラリから一旦ローカルな領域に上げたら、再度、呼び出した場合、ローカルな領域内に既に上げているプログラムを再使用する。  プログラムの処理部分で作業領域の初期化を行っていないと、前回の復帰時の作業領域の内容がそのまま残っている。  例えば5個のバッチジョブを同時実行し、~以降は変更ありません。

全文を見る
すると、全ての回答が全文表示されます。
回答No.10

#7、#9です。 整理します。 (1)非リユーザブル  毎回、ディスク上のライブラリから、ローカル領域に上がる。 (2)リユーザブル  ディスク上のライブラリから一旦ローカルな領域に上げたら、再度、呼び出した場合、前回の復帰時の作業領域の内容がそのまま残っている。  例えば5個のバッチジョブを同時実行し、ディスク上のライブラリにある同じサブルーチンを呼んだ場合、各バッチジョブが動いているローカル領域にそのサブルーチンがそれぞれ上がる。 →ディスク上のライブラリで見れば、同じサブルーチンが共用されているが、メモリ上での共用ではない。 (3)リエントラント  ディスク上のライブラリから、システム共通領域(あるいはマルチタスクが動くローカル領域)に上がり、処理部はマルチタスクでメモリ上共用されるが、作業領域は各タスク毎に独立した領域を確保・解放する。 →DBMSなどメモリ常駐で動くプログラムでは、初期処理でOSレベルの作業領域の確保を行い、その後に繰り返し動く多様なサブルーチンでは、その領域を使い回すといったことを行っている。 メモリ上での共用がないのに、不必要にリエントラントにすると、作業領域の確保・解放が繰り返され、フラグメンテーションの重大要因になる。

全文を見る
すると、全ての回答が全文表示されます。
回答No.9

#7回答者です。 #6さんへの追加質問ですが、汎用機の経験が長かったので横から回答します。 >ただ、このバッチから呼ばれる共通ルーチン(アベンドルーチンなど)は >どのモジュールから呼ばれることもあります。 >この共通ルーチンが動的に呼ばれる場合、共通ルーチンがロード上に >展開されますが、リエントラント仕様でないと変数域の上書きが >される可能性があると思ってよいのでしょうか? >それとも、複数のモジュールから呼ばれてメモリ上に展開する場合は、 >それぞれ別の領域に展開されるのでしょうか?(リエントラント不要) バッチなどは、すべてジョブ固有領域といったローカルな領域で実行され、そこから呼ばれるサブルーチンなども、システム共通領域に事前に上げておくといったことをしなければ、ローカルな領域にローディングされます。 DB/DC製品、DBなどとのミドルなどでずっとメモリ常駐された状態で、マルチタスクでオンラインなりバッチなりから繰り返し要求を受けて処理するようなプログラムは、リエントラントである必要があります。 逆にマルチタスクで動かないのに、不要にリエントラントにしたサブルーチンを繰り返しバッチやオンラインのユーザ空間から呼んだりすると、処理部分とは別に確保される変数などの作業領域が繰り返し確保・解放されることになり、フラグメンテーションが多発します。

全文を見る
すると、全ての回答が全文表示されます。
回答No.7

リエントラントの場合、処理部分はメモリ上で共用され、変数などの作業領域はリエントラントされる度に個々に確保・解放されます。 つまり、n回のリエントラントが発生した場合、所要メモリは、処理部分長+リエンラント回数×作業領域長になります。 そのため、リエントラント前提のプログラムは、変数宣言などの時に初期値を設定するのは意味がなく(コンパイラによっては、エラーになる場合もある)、処理部分で初期設定する必要があります。 プログラムを、ロードライブラリ(ハードディスク)からメモリに上げる処理は、かなりオーバーヘッドになります。そのため、繰り返し使用されるプログラムを、事前にメモリ上に上げメモリ常駐させて繰り返し使用するプログラムが、リエントラントに適しています。 その一方で、繰り返し作業領域の確保・解放が行われるので、フラグメンテーションが起こるというデメリットがあります。

全文を見る
すると、全ての回答が全文表示されます。
  • GOOD-Fr
  • ベストアンサー率32% (83/256)
回答No.6

マシン語を使える人なら、実は疑問に思いません。 「非再入可能」というのは、一般用語なのかもしれませんが、意味不明な日本語なので「リエントラント可能」と「リエントラント可能でない」と言い換えて説明します。 リエントラント可能でなくてもよい場合、あるサブルーチン、関数が使う変数はどこに取ってもかまいません。簡単に言えば「アドレス固定」でかまわないのです。つまり、「Aという変数は常に100番地にある」という考え方です。 が、リエントラントなプログラムではそうはいきません。このルーチンを半分ぐらい実行しているうちに、他のところからもこのルーチンを呼び出されてしまう、というのが、「リエントラント可能」ですから、「A という変数はいつも 100番地」というのは、都合が悪いのです。ふたつのルーチンで同一番地にアクセスしてお互いに書き換えてしまうわけですから。 これを回避するには、このルーチンに飛び込んでくるたびに「同じ名前の変数であっても違うアドレスが割り振られる」ことを保証する必要があります。通常、このためにはスタック上にフレームを生成し、フレームポインタからの相対アドレッシングを行なう必要があります。要するに「めんどくさい」のです。 ずいぶん昔の「計算機」には、このようなアドレッシングを簡単に行なえないものがあったため、リエントラントなルーチンを処理させることは「不必要に重い」処理であり、「できれば回避したい」というのが「プログラマにわざわざ指定させる」本当の意味だと思います。 もちろん、現在では C などをはじめとして「ローカル変数」という考え方を持つ言語が一般的であるため、フレームポインタを使った相対アドレッシングはほとんどの CPU でインプリメントされています。x86 でいえば、mov eax,[ebp+ebx+4*esi]というような命令もありますが、これはスタック上に作られたアドレス空間を指す EBP レジスタをフレームポインタとして使い、ローカル変数として定義された配列の先頭相対アドレスを EBX に格納しているときに、ESI 番目の配列要素をひとつの配列要素のサイズが 4バイトであるとしてアクセスし、EAX レジスタに格納するための命令です。 このへんの仕組みは、コンパイラを作成してみればいやでも理解できるようになると思います。 余談ですが、再帰可能なプログラムはリエントラントなプログラムですが、逆は必ずしも真ではありません。

noname#119141
質問者

お礼

ありがとうございます。ずいぶんと詳しいですね。 x86のアセンブラではなく汎用機のアセンブラを利用していますが、 意味は十分理解しました。ただ、もう少し不安なので、より現実的な 質問をさせてください。 汎用機において通常のバッチモジュールは、jobスケジュールに 従いシリアルに流れることが多いです。 この場合、リエントラントは不要であると思います。 ただ、このバッチから呼ばれる共通ルーチン(アベンドルーチンなど)は どのモジュールから呼ばれることもあります。 この共通ルーチンが動的に呼ばれる場合、共通ルーチンがロード上に 展開されますが、リエントラント仕様でないと変数域の上書きが される可能性があると思ってよいのでしょうか? それとも、複数のモジュールから呼ばれてメモリ上に展開する場合は、 それぞれ別の領域に展開されるのでしょうか?(リエントラント不要)

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

>頂いた回答にはプログラムが面倒というだけで、 >それさえ我慢すれば、RENTで問題なしと言っているように >思えますが違うのでしょうか? その通りです。 但し、私が回答したのは、コンパイルオプションで指定するのではなく、実際に作り込むときに、どちらの仕様で作るかを想定した場合のケースです。最近、COBOL、アセンブラから遠ざかっているので、以下は私の想像ですが、コンパイルオプションで非リエントラントを指定するメリットは、メモリを余り消費しないですむ、ということにあると、思っています。というのは、リエントラントの場合、全てのスレッド用に作業領域を確保する必要がありますが、非リエントラントとであれば、その必要はありません。また、内部で確保したメモリを自由に使い回しが出来ますので、メモリの使用量が少なくてすみます。 しかしながら、メモリの使用量を気にするのは、古き良き時代の話であり、最近はそのことを気にする必要がなくなっていますので、リエントラントを指定しておけば、問題ないと思います。只、自分の作るプログラムがマルチスレッド(昔はマルチタスクと言ってましたが)であることを要求されないのなら、コンパイル時に非リエントラントを指定しても問題ありません。

noname#119141
質問者

お礼

ありがとうございます。非常にわかりました。 メモリの使用量は、おっしゃるとおりですね。 さて、もう1つだけ、より現実的な話なのですが 汎用機において通常のバッチモジュールは、jobスケジュールに 従いシリアルに流れることが多いです。 この場合、リエントラントは不要であると思います。 ただ、このバッチから呼ばれる共通ルーチン(アベンドルーチンなど)は どのモジュールから呼ばれることもあります。 この共通ルーチンが動的に呼ばれる場合、共通ルーチンがロード上に 展開されますが、リエントラント仕様でないと変数域の上書きが される可能性があると思ってよいのでしょうか? それとも、複数のモジュールから呼ばれてメモリ上に展開する場合は、 それぞれ別の領域に展開されるのでしょうか?(リエントラント不要)

全文を見る
すると、全ての回答が全文表示されます。
noname#208124
noname#208124
回答No.4

絶対に複数から非同期で呼ばれることが無く再入可能にする意味が無いもの ・ブートローダーやOSのカーネルの初期化終了処理 非再入可能にせざるをえないもの ・組み込みなどでそのために割り当てるハードウェアリソースがない 歴史的事情 ・マルチスレッドなんてない時代に定義されて仕様上もう変えることが出来ないもの

noname#119141
質問者

お礼

とてもわかりました。 非再入可能にあえてする意味は、普通のプログラムにおいては あまりないと思ってよさそうですね。

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

まず、非再入可能の意味ですが、 「呼出したプログラムが、ちゃんと呼び出し元に戻らない」という意味ではありません。 非再入可能なプログラムも再入可能なプログラムのどちらも、きちんと、呼び出し元に戻ります。 では、再入可能とは何なのかと言うことですが、 これは、いまの言葉で言えば、スレッドセーフに該当します。つまり、複数のスレッドから、同時に呼ばれても、きちんと動作することを保証します。 非再入可能なプログラムのばあいは、複数のスレッドから同時に呼ばれた場合、正しく動作しません。 マルチスレッドプログラミングの場合は、再入可能かどうかが、非常に重要になりますが、一般的な、プログラミングの場合は、非再入可能なプログラムも再入可能なプログラムのどちらを使用しても、同じ事なので、あまり再入可能かどうかを気にしません。 非再入可能なプログラムの意義は、プログラムが簡単に作れるということです。再入可能なプログラムは、複数のスレッドから同時に呼び出された場合でも、正しい結果を保証しなければならないので、マルチスレッドに関する深い知識がないと、作れません。

noname#119141
質問者

お礼

回答ありがとうございます。 すみません。「元に戻らない」といった記載は間違いです。 中身が壊れることがあるということで記載したつもりでした。 さて、ちょっと古臭い言語で記載させて頂きますが、 COBOLやアセンブラのプログラムをコンパイル(アセンブル)する際に RENT(リエントラント)を指定するか,NORENTを指定するかを決めますが、 バッチであろうが、オンラインであろうが、 とりあえずRENTにしてればいいのではないか?と思うのですが、 どうなのでしょうか? アセンブラなら、GETMAINなどをソース上で指定しますが COBOLなどは勝手にコンパイルで保管してくれるなら RENT指定しておけば問題ないのではないかと思います。 頂いた回答にはプログラムが面倒というだけで、 それさえ我慢すれば、RENTで問題なしと言っているように 思えますが違うのでしょうか?

noname#119141
質問者

補足

また間違えました。 ≫複数スレッドからの処理の場合、中身が壊れる(上書きされる)ことがあるです。

全文を見る
すると、全ての回答が全文表示されます。
  • equinox2
  • ベストアンサー率48% (321/660)
回答No.2

「再入可能」の意味を取り違えていませんか? http://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%A8%E3%83%B3%E3%83%88%E3%83%A9%E3%83%B3%E3%83%88

noname#119141
質問者

お礼

すみません。 間違えですね。 それ以外は、No3の回答に記載します。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「再入可能」という言葉の意味を確認してください. すくなくとも「ちゃんと元に戻る」という意味ではありません.

noname#119141
質問者

お礼

すみません。 間違えですね。 それ以外は、No2の回答に記載します。

noname#119141
質問者

補足

ごめんなさい。 No3の回答に記載します。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • プログラム構造の「再帰的」について

    再帰的の説明に 「再帰的とは、あるプログラムがその内部から自分自身を呼び出して使用できる性質である。」「したがって再帰的であれば、必然的に再入可能でもある。」とありました。 ここで、「したがって再帰的であれば、必然的に再入可能でもある。」とは、つまり、プログラムAの中に再帰したプログラムA’が既に再入している状態にある、ということを表しているという理解かな?と思っているのですが、宜しいのでしょうか? より良い理解のために、補足説明などいただけたら、と思います。よろしくお願いいたします。

  • プログラムの構成について

    構成上どれがいいんでしょうか? 1.複数のプロセスで同時に実行できるようにしたプログラムは再帰的である。 2.逐次再使用可能なプログラムは、再入可能でもある。 3.再入可能プログラムはを実現するためには、プログラムを手続き部分とデータ部分に分割して、データ部分をプロセスごとにもつ必要がある。 4.再帰的処理のためには実行途中の状態をFIFO方式で記録し、制御する必要がある。

  • 恰好が悪いのですが、伺います。

    再入可能状態のプログラムルーチンが呼び出されている間には、 プロセス毎に使える領域が割り当てられている、 との主旨の説明を見掛けました。 但し、「複数回に渡って呼び出されたプログラムルーチンには、共有ロックが掛けられている。」との回答を別の質問ページで賜れましたので、 残念乍ら、私の誤解が残っているのだろう、と思われます。 従いまして、早急に分かりませんと、たとえ多くの参考書を読み耽りましても、 徒労に終わり兼ねませんから、畏れ入りますが、教えて下さい。 ★「プロセス毎に使える領域の『占有ロック』」が、 "再入可能プログラムルーチン"によって叶えられ得るのでしょうか?

  • プログラムから開くを使ってしまいました。

    Zipの解凍がうまくいかなかったので、いろいろ試している最中に何を思ったかマウスの右クリックをして「プログラムから開く」を選んでしまいました。そして、ウィンドウズフォトギャラリーとかウィンドウズエクスプローラーなど開くようになってしまいました。それで、パソコン内の全部のZipファイルが選択したプログラムで開くようになったようです。とりあえず、Zipの解凍がうまくいかなくていいから元に戻るようにしておかないとまた別のファイルをダウンロードしてもうまくいないことになるから困っています。うまく言葉で表現できていないからよくわからないかもしれませんが、普通に開いてうまくいかなかったから「プログラムから開く」をしてしまって元に戻らないということです。よろしくお願いします。困っております。

  • プログラムを作成したいのですが

    プログラムを作成したいと思っているのですが、何か見本になるようなプログラムは無いでしょうか? 自分では、まだ一から10までプログラムを作成できないのでよろしくお願いします。 ネットでは自分の作りたいように作成しなさいと、書いたりしてありましたが、転職用になにか打ち込みをしてみたいのです。 ゲームサンプルなど打ち込んでいるのですが、中々有意義なものではないので、プログラムサンプルを頂きたいのです。 よろしくお願いします。

  • 大学再入学か、編入か迷っています。

    大学再入学か、編入か迷っています。  今回、初めて質問する者です。自分は大学2年なのですが、現在在籍している大学の授業があまりにもひどく、動くなら早い内にと編入を考えています。 ですが、編入となると3年次からになり、たとえやりたい事があってもすぐに就活が始まり短い期間でしか学ぶ事が出来ないと思うのですが…。また1から学ぶ場合は再び大学を受験する考えもあるのですが、その場合仮に入る事ができても卒業する時の年齢が悩みになっています。(就職は年齢が左右すると聞いたため)それとこれは、個人的な事なのですが自分には下に弟がいるのですが再入学の場合は同じ学年になりそれも含め悩みになっています。 今の現状を解決するには早めに解決したいのですが、自分の回りには大学に進学した人が少なく相談ができない状況です。 立て続けの質問やつたない文でわかりにくく申し訳ないのですが、どなたかアドバイス頂ければ幸いです。  宜しくお願い致します。

  • "プログラムから開く"で

    先程パソコンの操作を誤り、"プログラムから開く"で間違ったプログラムを選択してしまいました。 その操作をしてから、デスクトップに表示されているコンピューター、コントロールパネル等以外のどのアイコンもwindows アドレス帳のものになっていて、クリックしてもアドレス帳が開かれてしまいます。どうすれば元の状態に戻せるのでしょうか? パソコンはあまり詳しくないので、用語が間違っていたり質問の意味を上手く伝えれられていなかったら申し訳ありません。

  • 継ぎ接ぎの様な質問文で畏れ入ります。

    (プロセス・スレッドではなく、)タスクによって 再入可能プログラムは別の記憶領域へ呼び出されていて、 其の各記憶領域の峻別の為に、 個別の局所変数が割り当てられるのでしょうか?

  • 正しいプログラムから開けない…。

    パソコン初心者なので説明不足や意味不明だったらすいませんっ。 マイピクチャにある画像ファイルを右クリックして、[プログラムから開く]で何かを変更してしまいました。 それからはいつも画像ファイルが別のプログラムで開くようになってしまいました。 (今は「Microsoft Office Picture Manager」というプログラムになっています。) もとはどんなプログラムになっていたのかも分かりません。だからもとに戻すことができません。 動画ファイルも保存しても、開くと静止で表示されるだけで、困っています。 動画ファイルも正常にもどれば、動くと思うんですが…。 どなたか教えてください。よろしくお願いします。

  • プログラムを始めるなら

    C言語をある程度知っている人なら、プログラミングは大丈夫だと言われる理由って何でしょう? 別にC言語を元に全てのプログラムができたわけでもないし、 オブジェクト指向のプログラムとは毛色が違うし。 私自身C言語,javaなどのソースが読める程度しかできませんが、 プログラミングが出来るとはお世辞にも言えません。 何故このような事が言われているのでしょう? また、最初に学ぶべき言語としてはやはりC等の言語がいいのでしょうか? それともアセンブリ言語のような物の方がいいのでしょうか?