Lab2
6617 ワード
Lab2 report
練習0:既存の実験を記入する
手動マージ:lab 2kerndebugkdebugを変更する.cとlab 2kerntraptrap.c 2つのファイルでいいです.
練習1:first-fit連続物理メモリ割り当てアルゴリズムを実現する
実験構想.
物理メモリページマネージャは、双方向チェーンテーブルに沿って空きメモリ領域を検索し、十分な空き領域が見つかるまで、チェーンテーブルをできるだけ少なく検索するための高速なアルゴリズムです.空き領域のサイズが申請割当のサイズとちょうど同じであれば、この空き領域を割り当てて、正常に戻ります.そうでなければ、この空きを2つの部分に分け、一部の領域は申請の割り当ての大きさと等しく、それを割り当て、残りの一部の領域は新しい空き領域を形成する.メモリを解放する設計は簡単で、この領域を双方向チェーンテーブルに戻すだけです.
じっけんプロセス
default_init_memmap()関数:
この関数は空きページチェーンテーブルを初期化するために使用され、主に2つのステップがある:a.各空きページを初期化する;b.空きページの合計数を計算します.static void
default_init_memmap(struct Page *base, size_t n) {
assert(n > 0);
struct Page *p = base;
for (; p != base + n; p ++) {
assert(PageReserved(p));//
p->flags = p->property = 0;//
SetPageProperty(p);
set_page_ref(p, 0);//
list_add_before(&free_list, &(p->page_link));// ,
}
base->property = n;
nr_free += n;//
}
default_alloc_pages()関数:
この関数は空きページを割り当てるために使用されます.具体的な手順は、a.十分な空きブロックを探して、見つかったら、フラグビットを再設定して、空きチェーンテーブルからこのページを削除します.b.空きブロックの大きさが適切かどうかを判断し、適切でなければ、ページブロックを分割し、適切であれば操作しない.c.残りの空きページ数を計算する.d.割り当てられたページブロックアドレスを返します.static struct Page *
default_alloc_pages(size_t n) {
assert(n > 0);
if (n > nr_free) {
return NULL;
}
struct Page *page = NULL;
list_entry_t *le = &free_list;
//
while ((le = list_next(le)) != &free_list) {
struct Page *p = le2page(le, page_link);
// !
if (p->property >= n) {
page = p;
int i;
struct Page *pp;
list_entry_t *temp_le;
temp_le = le;
for(i=0; iproperty > n) {
struct Page *p = page + n;
p->property = page->property - n;
}
nr_free -= n;
}
return page;
}
default_free_pages()関数:
この関数の役割は、使用済みのページを解放し、freelistにマージすることであり、具体的には、a.freelistで適切な位置を検索してb.を挿入するためにリリースされたページのフラグビットを変更し、ヘッダのカウンタc.freelistで高アドレスまたは低アドレスにマージしようとするstatic void
default_free_pages(struct Page *base, size_t n) {
assert(n > 0);
assert(PageReserved(base));//
struct Page *p = base;
list_entry_t *le = &free_list;
//
while((le=list_next(le))!= &free_list){
p = le2page(le, page_link);
if(p>base){
break;
}
}
// n ,
for (p=base; p < base + n; p ++) {
list_add_before(le, &(p->page_link));
p->flags = 0;
set_page_ref(p, 0);
ClearPageReserved(p);
SetPageProperty(p);
}
//
base->property = n;
//
p = le2page(le, page_link);
if (base + n == p) {
base->property += p->property;
p->property = 0;
}
//
le = list_prev(&(base->page_link));
p = le2page(le, page_link);
if(le!=&free_list && p==base-1){
while(le!=&free_list){
if(p->property){
p->property+=base->property;
base->property = 0;
break;
}
le=list_prev(le);
p=le2page(le,page_link);
}
}
nr_free += n;
}
改善点
検索アルゴリズムを改善して、検索速度を速めることができるかもしれません.
練習2:仮想アドレスを探すページ・テーブル・アイテムの実装
実験構想.
ページテーブルのアドレスを取得してみます.取得できない場合は、新しいページテーブルを作成します.
インプリメンテーションプロセス
get_pte()関数:
pte_t *
get_pte(pde_t *pgdir, uintptr_t la, bool create) {
pde_t *pdep = &pgdir[PDX(la)];
//
if(!(*pdep & PTE_P)){
struct Page *page;
//
if(!create || (page = alloc_page())==NULL){
return NULL;
}
set_page_ref(page, 1); // 1
uintptr_t pa = page2pa(page);//
memset(KADDR(pa),0,PGSIZE);
*pdep = pa| PTE_U| PTE_W| PTE_P;//
}
//
return &((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)];
}
思考問題
ページ・ディレクトリ・アイテム(Pag Director Entry)とページ・テーブル(Page Table Entry)の各コンポーネントの意味とucoreに対する潜在的な使用方法について説明してください。
ページディレクトリ項目PDE=(ページ表開始物理アドレス&(~0 x 01FFF)|PTE_U | PTE_W | PTE_P. PDEの上位20ビットは、ページ表の開始アドレス、PTE_を表します.Uは、ユーザ状態ソフトウェア読み取り可能な物理メモリページの内容を示し、PTE_Wは物理メモリページ書き込み可能、PTE_Pは物理メモリページが存在することを示す.潜在的な用途:双方向チェーンテーブルとして現在のすべてのページの物理アドレスと論理アドレスの対応を格納し、置換アルゴリズムで変換されたページを選択します.
ページ表項目PTE=(pa&(~0 x 01FFF)|PTE_P | PTE_W PTEの上位20ビットは、そのページに対応する物理アドレスの上位20ビット(上位20ビットから対応するページに位置決め可能)、PTE_PとPTE_Wの意味はPDE中の対応ビットと同じPTEのインデックスが線形アドレス中の高さ11~20ビットである.潜在的な用途:ページテーブル(Page Table Entry)には、置換アルゴリズムで置換されたページの情報が格納され、置換後に物理アドレスにマッピングされます.
ucore実行中にメモリにアクセスし、ページアクセス異常が発生した場合、ハードウェアはどのようなことをしますか?
ハードウェアは、まずオペレーティングシステムから与えられた割り込みを受け入れ、その後、ページを変更する操作を行う.すなわち、ページアクセス異常が発生すると、CPUは、ページアクセス異常を引き起こす線形アドレスをレジスタCR 2に装着し、エラーコードerrorCodeを与え、ucoreOSはこの値をstruct trapframeにtf_Errメンバー変数.中断サービスルーチンは、ページアクセス異常処理関数do_を呼び出すpgfaultは具体的な処理を行う.
練習3:ダミー・アドレスが存在するページを解放し、対応する2次ページ・テーブル・アイテムのマッピングを解除します。
実験構想.
このページが参照された回数を判断し、一度だけ参照された場合、このページを解放することもできます.それ以外の場合は、ページテーブルのエントリのみを解放できます.
インプリメンテーションプロセス
page_remove_pte()関数:
static inline void
page_remove_pte(pde_t *pgdir, uintptr_t la, pte_t *ptep) {
//
if (*ptep & PTE_P){
struct Page* page = pte2page(*ptep);
if (page_ref_dec(page)==0){
free_page(page);// 1
}
*ptep = 0;
tlb_invalidate(pgdir, la);// pte
}
}
思考問題
データ構造Pageのグローバル変数(実際には配列)の各項目は、ページ・テーブルのページ・ディレクトリ・アイテムとページ・テーブル・アイテムに対応していますか?もしあったら、その対応関係は何ですか?
あります.ページ・ディレクトリ・アイテムまたはページ・テーブル・アイテムの上位20ビットは、どのPageに対応するかを示します.
仮想アドレスが物理アドレスと等しい場合は、lab 2をどのように修正して完了する必要がありますか?プログラミングを通じてこの問題を具体的に完成することを奨励します。
付録C.リンクアドレス/ロードアドレス/ダミーアドレス/物理アドレスから分かるように、ダミーアドレスと物理アドレスの間にオフセットがあり、すなわちマッピング関係がある.phy addr + KERNBASE = virtual addr
KERNBASEは、仮想アドレス空間におけるカーネルベースアドレス、すなわちオフセット量である.lab 2/kern/mm/memlayoutを表示h,その定義を知ったKERNBASEは:#define KERNBASE 0xC0000000 。
これを0 x 0 x 0に変更すると、仮想アドレスと物理アドレスが等しくなります.
static void
default_init_memmap(struct Page *base, size_t n) {
assert(n > 0);
struct Page *p = base;
for (; p != base + n; p ++) {
assert(PageReserved(p));//
p->flags = p->property = 0;//
SetPageProperty(p);
set_page_ref(p, 0);//
list_add_before(&free_list, &(p->page_link));// ,
}
base->property = n;
nr_free += n;//
}
static struct Page *
default_alloc_pages(size_t n) {
assert(n > 0);
if (n > nr_free) {
return NULL;
}
struct Page *page = NULL;
list_entry_t *le = &free_list;
//
while ((le = list_next(le)) != &free_list) {
struct Page *p = le2page(le, page_link);
// !
if (p->property >= n) {
page = p;
int i;
struct Page *pp;
list_entry_t *temp_le;
temp_le = le;
for(i=0; iproperty > n) {
struct Page *p = page + n;
p->property = page->property - n;
}
nr_free -= n;
}
return page;
}
static void
default_free_pages(struct Page *base, size_t n) {
assert(n > 0);
assert(PageReserved(base));//
struct Page *p = base;
list_entry_t *le = &free_list;
//
while((le=list_next(le))!= &free_list){
p = le2page(le, page_link);
if(p>base){
break;
}
}
// n ,
for (p=base; p < base + n; p ++) {
list_add_before(le, &(p->page_link));
p->flags = 0;
set_page_ref(p, 0);
ClearPageReserved(p);
SetPageProperty(p);
}
//
base->property = n;
//
p = le2page(le, page_link);
if (base + n == p) {
base->property += p->property;
p->property = 0;
}
//
le = list_prev(&(base->page_link));
p = le2page(le, page_link);
if(le!=&free_list && p==base-1){
while(le!=&free_list){
if(p->property){
p->property+=base->property;
base->property = 0;
break;
}
le=list_prev(le);
p=le2page(le,page_link);
}
}
nr_free += n;
}
pte_t *
get_pte(pde_t *pgdir, uintptr_t la, bool create) {
pde_t *pdep = &pgdir[PDX(la)];
//
if(!(*pdep & PTE_P)){
struct Page *page;
//
if(!create || (page = alloc_page())==NULL){
return NULL;
}
set_page_ref(page, 1); // 1
uintptr_t pa = page2pa(page);//
memset(KADDR(pa),0,PGSIZE);
*pdep = pa| PTE_U| PTE_W| PTE_P;//
}
//
return &((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)];
}
static inline void
page_remove_pte(pde_t *pgdir, uintptr_t la, pte_t *ptep) {
//
if (*ptep & PTE_P){
struct Page* page = pte2page(*ptep);
if (page_ref_dec(page)==0){
free_page(page);// 1
}
*ptep = 0;
tlb_invalidate(pgdir, la);// pte
}
}
phy addr + KERNBASE = virtual addr
#define KERNBASE 0xC0000000 。