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

假设使用正确的工具,Segfault 非常容易找到。通常我只是开始gdb,查看回溯并立即知道原因。因此,我没有通过您的代码(我没有),而是给您一个通用的方法来查找任何段错误(以及许多其他错误):

如果您在 Linux 系统上使用 GCC,我建议您使用-Wall -g -ggdb -O0. -Wall将显示有趣的警告,这通常是未定义行为或段错误的原因,-g -ggdb并向您的代码添加一些有用的调试信息并-O0禁用优化(因此循环内的计数器变量不会被优化等等)。

之后,您应该使用gdb ./yourprog. 然后编写run以启动您的程序。在你的程序崩溃后,你会看到类似“得到段错误,程序退出...”。类型bt显示回溯(即函数调用堆栈,包括行号等)。只需查看列表并搜索属于程序一部分的第一个最顶层文件。这样,您现在将知道发生段错误的确切位置(文件和行号),通常如果您确定原因是什么则非常容易知道确切的行(只需考虑该语句中可能未初始化或为 NULL 的内容)。

或者,您也可以breakpoint yourfile.c:123在该行设置 a(在此示例中为行号 123)并使用 显示变量的内容print your_var_or_pointer。检查该行中的所有变量-现在您应该终于知道原因是什么了:D

(PS:我不能给你建议如何在 Visual Studio 等其他环境中调试,但想法是一样的。它们都附带了一个优秀的调试器!)

于 2011-04-14T07:15:08.983 回答