0

マシンコードのプログラムがメモリからレジスタに値をロードしたり、ジャンプを実行したり、レジスタに値をメモリに格納したりする方法は理解していますが、これが複数のプロセスでどのように機能するかはわかりません。プロセスにはその場でメモリが割り当てられるので、相対アドレス指定を使用する必要がありますか?これは自動的に行われますか(相対ジャンプなどを実行するアセンブリ命令があることを意味します)、またはプログラムはアドレス指定するすべてのメモリ位置に正しいオフセットを「手動で」追加する必要がありますか。

マルチタスクに関してもう1つ質問がありますが、これは多少関連しています。実行されていないOSは、どのようにしてスレッドを停止し、次のスレッドに進みますか。これは時限割り込みで行われますか?もしそうなら、どのようにしてレジスターの値をスレッドのために保存することができますか。制御が別のスレッドに与えられる前に、それらはメモリに保存されますか?または、時限割り込みではなく、スレッドは単に制御を放棄するのに適した時間を選択しますか。時限割り込みの場合、スレッドにプロセッサ時間が与えられ、それを必要としない場合はどうなりますか。それを無駄にする必要がありますか、それは手動で割り込みを呼び出すことができますか、それとも多くの時間を必要としないことをOSに警告しますか?

編集:または、実行可能ファイルを実行する前に編集して、正しいオフセットを補正しますか?

4

3 に答える 3

2

それはそれがどのように機能するかではありません。最新のオペレーティング システムはすべて、使用可能なメモリを仮想化します。すべてのプロセスに、2 ギガバイト (またはそれ以上) のメモリがあり、それを誰とも共有する必要がないという錯覚を与えます。これを行うマシンの重要なコンポーネントはMMUで、最近ではプロセッサ自体に組み込まれています。この仮想化のもう 1 つの重要な機能は、プロセスを分離することです。1 つの不正行為は、別の 1 つをダウンさせることはできません。

はい、クロックティック割り込みは、現在実行中のコードを中断するために使用されます。プロセッサの状態はスタックに保存されます。次に、オペレーティング システムのスケジューラは、実行する準備ができていて、優先度が十分に高く、最初に実行できるスレッドがあるかどうかを確認します。いくつかの追加コードにより、全員が公平に分配されることが保証されます。次に、他のスレッドで実行を再開するように MMU を設定するだけです。実行可能なスレッドがない場合、CPU は HALT 命令で物理的にオフになります。次のクロック割り込みで再び起こされます。

これは 1 万フィートのビューであり、オペレーティング システムの設計に関するどの本でも十分にカバーされています。

于 2012-04-17T05:49:01.757 に答える
1

プロセスにはオンザフライでメモリが割り当てられるので、相対アドレス指定を使用する必要がありますか?

いいえ、何に対処しようとしているかに応じて、相対または絶対アドレス指定を使用できます。

少なくとも歴史的には、さまざまなアドレッシング モードは、ローカル メモリとリモート メモリに重点を置いていました。相対アドレッシングは現在のアドレスに近いメモリ アドレス用であり、絶対アドレッシングはより高価でしたが、何でもアドレス指定できました。最新の仮想メモリ システムでは、これらの区別は不要になる可能性があります。

プロセスにはオンザフライでメモリが割り当てられるので、相対アドレス指定を使用する必要がありますか? これは自動的に行われますか(相対ジャンプなどを実行するアセンブリ命令があることを意味します)、またはプログラムがアドレス指定するすべてのメモリ位置に正しいオフセットを「手動で」追加する必要がありますか。

これについてはよくわかりません。これは通常、コンパイラによって処理されます。繰り返しますが、最新の仮想メモリ システムでは、この複雑さが不要になります。

制御が別のスレッドに渡される前に、それらはメモリに保存されますか?

はい。通常、すべての状態 (レジスターなど) はプロセス制御ブロック (PCB) に保管され、新しいコンテキストがロードされ、レジスターやその他のコンテキストが新しい PCB からロードされ、新しいコンテキストで実行が開始されます。PCB は、スタックまたはカーネル メモリに保存するか、プロセッサ固有の操作を利用してこのプロセスを最適化できます。

または、時限割り込みではなく、スレッドが制御を放棄するのに適切なタイミングを単に選択します。

スレッドは制御を譲ることができます。つまり、実行キューの最後にスレッド自体を戻します。また、IO またはスリープを待機することもできます。その後、スレッド ライブラリはスレッドを待機キューに入れ、別のコンテキストに切り替えます。IO の準備が完了するか、スリープが終了すると、スレッドは実行キューに戻されます。ミューテックス ロックでも同じことが起こります。待ち行列でロックを待ちます。ロックが使用可能になると、スレッドは実行キューに戻されます。

時限割り込みの場合、スレッドにプロセッサ時間が与えられ、それを必要としない場合はどうなりますか。それを無駄にする必要がありますか、手動で割り込みを呼び出すことができますか、それともあまり時間が必要ないことを OS に警告しますか?

スレッドが実行できる (CPU 命令を実行する) か、待機中 (IO またはスリープ) のいずれかです。譲歩を要求することはできますが、通常は [再び] スリープするか、IO を待機することによって譲歩します。

于 2012-04-17T05:04:49.617 に答える
0

私はおそらくこの質問にかなり遅れて立ち入りましたが、それから、他のプログラマーに役立つかもしれません. まず - 理論。

現代のオペレーティング システムはメモリを仮想化し、そのためにシステム メモリ領域内に一連のページ ポインタを保持します。各ページは固定サイズ (通常は 4K) であり、プログラムがメモリをシークすると、割り当てられたメモリ アドレスがメモリ ページ ポインタを使用して仮想化されます。これは、前世代のプロセッサの「セグメント」レジスタの動作に似ています。

スケジューラが別のプロセスを実行することを決定した場合、以前のプロセスをメモリに保持する場合と保持しない場合があります。それがメモリに保持されている場合、スケジューラはレジスタのスナップショット全体を保存するだけです (現在、YMM レジスタを含む - コンテキスト全体を保存する単一の命令がないため、このビットは以前は複雑な問題でした: XSAVE を参照してください)。 )、これは固定形式です (Intel SW マニュアルで入手可能)。これは、使用されていたメモリ ページに関する情報とともに、スケジューラ自体のメモリ空間に格納されます。

ただし、スケジューラがスリープ状態になろうとしている現在のプロセス コンテキストをハードディスクに「ダンプ」する必要がある場合、通常、この状況は、ウェイクアップ中のプロセスが異常な量のメモリを必要とする場合に発生し、スケジューラはメモリ ページを書き込みます。ディスクブロック内のファイル (ページファイルと呼ばれる - メモリの予約領域 - ページファイルは実メモリのサイズと等しくなければならないという「おばあさんの知恵」の源でもあります) と、スケジューラはメモリページポインタアドレスをページファイルのオフセットとして保存します。起動すると、スケジューラはページファイルからオフセット アドレスを読み取り、実メモリを割り当ててメモリ ページ ポインタを設定し、ディスク ブロックからコンテンツをロードします。

ここで、特定の質問に答えるには: 1. 相対アドレス指定のみを使用する必要がありますか、それとも絶対アドレス指定を使用できますか?

と。いずれかを使用できます-メモリページポインターがそのアドレスを目に見えない形式で相対化するため、絶対的であると認識しているものはすべて相対的です。オペレーティングシステム自体のカーネルを除いて、絶対的なメモリアドレスはどこにもありません (io デバイスメモリを含む)。これをテストするには、任意の .EXE プログラムをアンアセンブルして、エントリ ポイントが常に CALL 0010 であることを確認します。これは、各スレッドが異なる "0010" を取得して実行を開始することを明確に意味します。

  1. スレッドはどのように生命を得るのですか? また、未使用のスライスを放棄した場合はどうなりますか?

答え。スレッドは通常、スライスを取得します - 現代のシステムは通常の標準として 20 ミリ秒です - しかし、これは、処理するハードウェア割り込みが多くないサーバーの特別な目的のコンパイルで変更されることがあります - プロセスキューでの位置の順序で。スレッドは通常、関数 sleep() を呼び出すことによってそのスライスを放棄します。これは、タイム スライスの残りの部分を放棄するための正式な (そして非常に優れた方法) です。非同期読み取りまたは割り込みアクションを実装するほとんどのライブラリは、sleep() を内部的に呼び出しますが、多くの場合、最上位プログラムも sleep() を呼び出します。たとえば、タイム ギャップを作成するためです。スリープを呼び出すと、プロセス コンテキストが確実に変更されます。実際には、CPU には NOP を使用してスリープする自由が与えられていません。

もう 1 つの方法は、IO が完了するのを待つことであり、これは別の方法で処理されます。IO プロセスを要求するプログラムは、そのタイム スライスを譲ります。プロセス スケジューラは、このスレッドに「WAITING FOR AN IO」状態であることを示すフラグを立てます。このスレッドには、意図した IO まで、プロセッサによってタイム スライスが与えられません。完了するか、タイムアウトします。この機能は、sleep_until_IO() のようなインターフェイスを明示的に記述する必要がないため、プログラマーに役立ちます。

これにより、探索をさらに進めることができると信じてください。

于 2015-03-27T15:58:16.573 に答える