0

オペレーティング システムのクラスで、翻訳ルックアサイド バッファーをシミュレートする予定のプロジェクトがあります。

TLBミスの後に呼び出されるメソッドを書いています。空であるか、しばらくヒットしていない TLB 内の次のエントリを見つけ、そのエントリを削除し、最後に呼び出されたページ テーブルのエントリに置き換えます。メソッドが呼び出されると、ページ テーブル エントリのデータが与えられます。

Void tlb_insert(VPAGE_NUMBER new_vpage, PAGEFRAME_NUMBER new_pframe, BOOL new_mbit, BOOL new_rbit)
{
  // Starting at the clock_hand'th entry, find first entry to
  // evict with either valid bit  = 0 or the R bit = 0. If there
  // is no such entry, then just evict the entry pointed to by
  // the clock hand.

  int m;
  int evct = clock_hand;
  for (m = clock_hand; m < (num_tlb_entries); m++){
    if (tlb[m].vbit_and_vpage & VBIT_MASK == 0 || tlb[m].mr_pframe & RBIT_MASK == 0){
      evct = m;

      break;
    }
  }

  // Then, if the entry to evict has a valid bit = 1,
  // write the M and R bits of the of entry back to the M and R
  // bitmaps, respectively, in the MMU (see mmu_modify_rbit_bitmap, etc.
  // in mmu.h)

  if (tlb[evct].vbit_and_vpage & VBIT_MASK == 1){
    PAGEFRAME_NUMBER pfr = tlb[evct].mr_pframe & PFRAME_MASK;
    int val1 = tlb[evct].mr_pframe & RBIT_MASK;
    int val2 = tlb[evct].mr_pframe & MBIT_MASK;
    mmu_modify_rbit_bitmap (pfr, val1);
    mmu_modify_mbit_bitmap(pfr, val2);
  }

  // Then, insert the new vpage, pageframe, M bit, and R bit into the
  // TLB entry that was just found (and possibly evicted).
   tlb[evct].vbit_and_vpage = VBIT_MASK | new_vpage;
   tlb[evct].mr_pframe = new_mbit | (new_rbit | new_pframe); 
  // Finally, set clock_hand to point to the next entry after the
  // entry found above.
  clock_hand = evct + 1;
}

//Writes the M  & R bits in the each valid TLB
//entry back to the M & R MMU bitmaps.
 void tlb_write_back()
{
   int n;
  for (n = 0; n < num_tlb_entries; n++){
    if (tlb[n].vbit_and_vpage & VBIT_MASK == 1){
       PAGEFRAME_NUMBER pfr = tlb[n].mr_pframe & PFRAME_MASK;
       int val1 = tlb[n].mr_pframe & RBIT_MASK;
       int val2 = tlb[n].mr_pframe & MBIT_MASK;
       mmu_modify_rbit_bitmap (pfr, val1);
       mmu_modify_mbit_bitmap(pfr, val2); 
    }   
    } 
  } 

次の行からセグメンテーション違反が発生しています。

tlb[evct].vbit_and_vpage = VBIT_MASK | new_vpage;
tlb[evct].mr_pframe = new_mbit | (new_rbit | new_pframe); 

VBIT_MASK は、挿入するビットをマスクするために以前に定義された変数です。ビットマスクの使い方を誤解しているのか、コードにもっと深刻な問題があるのか​​ どうかはわかりません。誰かにすべてを詳しく説明してもらうのは大変だと思いますが、これを修正するためにどの方向に考えるべきかについて誰か提案があれば、感謝します!

4

2 に答える 2

4

&この表が驚くほど低いことに注意してください。

$ cat /usr/share/misc/operator
Operator                                        Associativity
-------------------------------------------------------------
() [] -> .                                      left to right
! ~ ++ -- - (type) * & sizeof new delete        right to left
->* .*                                          left to right
* / %                                           left to right
+ -                                             left to right
<< >>                                           left to right
< <= > >=                                       left to right
== !=                                           left to right
&                                               left to right
^                                               left to right
|                                               left to right
&&                                              left to right
||                                              left to right
?:                                              right to left
= += -= *= /= %= <<= >>= &= ^= |= throw         right to left
?: (C++, third operand)                         right to left
,                                               left to right

$FreeBSD: src/share/misc/operator,v 1.2.22.1 2009/05/31 18:14:24 ed Exp $
于 2011-04-14T07:01:21.877 に答える
2

適切なツールがあれば、セグメンテーション違反は非常に簡単に見つけることができます。通常、私はただ始めgdbて、バックトレースを見て、すぐに理由を知ります。したがって、コードを調べる代わりに (私にはありません)、セグメンテーション違反 (および他の多くのエラー) を見つけるための一般的なレシピを提供します。

Linux システムで GCC を使用している場合は、 を使用してコードを (再) コンパイルすることをお勧めします-Wall -g -ggdb -O0-Wall多くの場合、未定義の動作やセグメンテーション違反の原因となる興味深い警告を表示-g -ggdbし、コードにいくつかの有用なデバッグ情報を追加し、-O0最適化を無効にします (ループ内のカウンター変数が最適化されないようにするなど)。

その後、デバッガーを起動する必要がありますgdb ./yourprog。次にrun、プログラムを開始するために書き込みます。プログラムがクラッシュした後、「got segfault, program exited with ...」のようなメッセージが表示されます。btバックトレース (つまり、行番号などを含む関数呼び出しのスタック) を表示するタイプです。リストを見てください。プログラムの一部である最初の最上位ファイルを検索すると、segfault が発生している正確な場所 (ファイルと行番号) がわかります。正確な行を知っている(そのステートメントで何がユニット化されているか、または NULL であるかを考えてみてください)。

または、breakpoint yourfile.c:123その行 (この例では行番号 123) に を設定し、 で変数の内容を表示することもできますprint your_var_or_pointer。その行のすべての変数を調べます-これで、最終的に原因がわかりました:D

(PS: Visual Studio などの他の環境でのデバッグ方法についてアドバイスすることはできませんが、考え方は同じです。すべてに優れたデバッガーが付属しています!)

于 2011-04-14T07:15:08.983 に答える