我的操作系统类中有一个项目,我应该模拟一个转换后备缓冲区。
我正在编写一个在TLB-miss之后调用的方法。它应该在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是一个先前定义的变量,用于屏蔽我现在要插入的位。我不确定我是否误解了如何使用位掩码,或者我的代码是否存在更严重的错误。我意识到要求任何人详细介绍整个事情是太过分了,但如果有人对我应该考虑的方向有任何建议,我会很感激!
答案 0 :(得分: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 $
答案 1 :(得分:2)
如果使用合适的工具,很容易找到Segfaults。通常我只是启动gdb
,查看回溯并立即知道原因。因此,我只是给你一个通用的配方来找到任何段错(以及许多其他错误),而不是通过你的代码(我没有):
如果您在Linux系统上使用GCC,我建议您使用-Wall -g -ggdb -O0
(重新)编译代码。 -Wall
将显示有趣的警告,这些警告通常是未定义行为或段错误的原因,-g -ggdb
会为您的代码添加一些有用的调试信息,并-O0
禁用优化(以便循环中的计数器变量)没有优化等等。
之后,您应该使用gdb ./yourprog
启动调试器。然后写run
来启动你的程序。程序崩溃后,您将看到类似“获得段错误,程序退出...”的类型。键入bt
,显示回溯(即函数调用堆栈,包括行号等)。只需查看列表并搜索作为程序一部分的第一个最顶层文件。通过它,您现在将知道发生段错误的确切位置(文件和行号),通常它非常容易确定如果您知道确切的行,那么原因是什么(只考虑可能在该语句中可能是单元化的或者是NULL)。
或者,您也可以在该行设置breakpoint yourfile.c:123
(在此示例中为行号123),并使用print your_var_or_pointer
显示变量的内容。检查该行中的所有变量 - 现在你应该知道原因是什么:D
(PS:我不能给你如何在Visual Studio等其他环境中进行调试的建议,但想法是一样的。它们都带有一个优秀的调试器!)