中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網(wǎng)站招標書怎么做香港seo公司

網(wǎng)站招標書怎么做,香港seo公司,企業(yè)網(wǎng)站關(guān)鍵詞放幾個,河南網(wǎng)站建設在本實驗室中,您將探索頁表并對其進行修改,以簡化將數(shù)據(jù)從用戶空間復制到內(nèi)核空間的函數(shù)。 開始編碼之前,請閱讀xv6手冊的第3章和相關(guān)文件: kernel/memlayout.h,它捕獲了內(nèi)存的布局。kernel/vm.c,其中包含…

在本實驗室中,您將探索頁表并對其進行修改,以簡化將數(shù)據(jù)從用戶空間復制到內(nèi)核空間的函數(shù)。

開始編碼之前,請閱讀xv6手冊的第3章和相關(guān)文件:

  • kernel/memlayout.h,它捕獲了內(nèi)存的布局。
  • kernel/vm.c,其中包含大多數(shù)虛擬內(nèi)存(VM)代碼。
  • kernel/kalloc.c,它包含分配和釋放物理內(nèi)存的代碼。

1.kernel/memlayout.h

這段代碼和注釋描述了QEMU虛擬化環(huán)境中的物理內(nèi)存布局,特別是RISC-V架構(gòu)下的內(nèi)存布局。它定義了各種硬件設備和內(nèi)存區(qū)域的物理地址,以及內(nèi)核如何使用這些內(nèi)存區(qū)域。

// Physical memory layout// qemu -machine virt is set up like this,
// based on qemu's hw/riscv/virt.c:
//
// 00001000 -- boot ROM, provided by qemu
// 02000000 -- CLINT
// 0C000000 -- PLIC
// 10000000 -- uart0 
// 10001000 -- virtio disk 
// 80000000 -- boot ROM jumps here in machine mode
//             -kernel loads the kernel here
// unused RAM after 80000000.// the kernel uses physical memory thus:
// 80000000 -- entry.S, then kernel text and data
// end -- start of kernel page allocation area
// PHYSTOP -- end RAM used by the kernel// qemu puts UART registers here in physical memory.
#define UART0 0x10000000L
#define UART0_IRQ 10// virtio mmio interface
#define VIRTIO0 0x10001000
#define VIRTIO0_IRQ 1// local interrupt controller, which contains the timer.
#define CLINT 0x2000000L
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.// qemu puts programmable interrupt controller here.
#define PLIC 0x0c000000L
#define PLIC_PRIORITY (PLIC + 0x0)
#define PLIC_PENDING (PLIC + 0x1000)
#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100)
#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100)
#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000)
#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000)
#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000)
#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000)// the kernel expects there to be RAM
// for use by the kernel and user pages
// from physical address 0x80000000 to PHYSTOP.
#define KERNBASE 0x80000000L
#define PHYSTOP (KERNBASE + 128*1024*1024)// map the trampoline page to the highest address,
// in both user and kernel space.
#define TRAMPOLINE (MAXVA - PGSIZE)// map kernel stacks beneath the trampoline,
// each surrounded by invalid guard pages.
#define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)// User memory layout.
// Address zero first:
//   text
//   original data and bss
//   fixed-size stack
//   expandable heap
//   ...
//   TRAPFRAME (p->trapframe, used by the trampoline)
//   TRAMPOLINE (the same page as in the kernel)
#define TRAPFRAME (TRAMPOLINE - PGSIZE)

QEMU虛擬機中的物理內(nèi)存布局

QEMU模擬的機器virt的內(nèi)存布局如下:

  1. 0x00001000 - 啟動ROM,由QEMU提供。
  2. 0x02000000 - CLINT (Core Local Interruptor),負責管理本地中斷,包括定時器中斷。
  3. 0x0C000000 - PLIC (Platform-Level Interrupt Controller),負責處理外部中斷。
  4. 0x10000000 - uart0,串口控制器。
  5. 0x10001000 - virtio磁盤接口。
  6. 0x80000000 - 啟動ROM會在機器模式下跳轉(zhuǎn)到這里,內(nèi)核也會加載到這里。
  7. 0x80000000 以后的內(nèi)存區(qū)域為內(nèi)核和用戶空間的使用。

內(nèi)核物理內(nèi)存使用情況

  • 0x80000000 - 內(nèi)核的入口點,包含entry.S,以及內(nèi)核的代碼和數(shù)據(jù)。
  • end - 內(nèi)核頁分配區(qū)域的開始。
  • PHYSTOP - 內(nèi)核使用的內(nèi)存結(jié)束位置。

硬件設備的地址定義

以下宏定義了各個硬件設備在物理內(nèi)存中的地址和中斷號:

UART0UART0_IRQ

#define UART0 0x10000000L
#define UART0_IRQ 10

Virtio磁盤接口

#define VIRTIO0 0x10001000
#define VIRTIO0_IRQ 1

CLINT 和相關(guān)寄存器地址:

#define CLINT 0x2000000L
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
#define CLINT_MTIME (CLINT + 0xBFF8) // 啟動以來的時鐘周期數(shù)

PLIC 和相關(guān)寄存器地址:

#define PLIC 0x0c000000L
#define PLIC_PRIORITY (PLIC + 0x0)
#define PLIC_PENDING (PLIC + 0x1000)
#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100)
#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100)
#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000)
#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000)
#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000)
#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000)

內(nèi)核內(nèi)存布局

  • KERNBASEPHYSTOP

    #define KERNBASE 0x80000000L
    #define PHYSTOP (KERNBASE + 128*1024*1024) // 內(nèi)核使用的內(nèi)存大小為128MB
    

    TRAMPOLINE

    #define TRAMPOLINE (MAXVA - PGSIZE)
    

    內(nèi)核棧的地址計算

    #define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)
    

    用戶內(nèi)存布局

    用戶地址空間從零地址開始,包含以下部分:

  • 文本段
  • 原始數(shù)據(jù)段和BSS段
  • 固定大小的棧
  • 可擴展的堆
  • TRAPFRAME
#define TRAPFRAME (TRAMPOLINE - PGSIZE)

TRAMPOLINE:與內(nèi)核中的相同頁面。

2.?kernel/vm.c

這段代碼實現(xiàn)了一個基于RISC-V架構(gòu)的內(nèi)核頁表管理模塊,主要用于管理虛擬內(nèi)存與物理內(nèi)存之間的映射。下面是對這段代碼中各個函數(shù)和宏定義的詳細解釋:

#include "param.h"
#include "types.h"
#include "memlayout.h"
#include "elf.h"
#include "riscv.h"
#include "defs.h"
#include "fs.h"/**該函數(shù)創(chuàng)建一個直接映射的內(nèi)核頁表,并將硬件設備、內(nèi)核代碼和數(shù)據(jù)段、以及跳板頁(trampoline)映射 *到內(nèi)核頁表中。*/
pagetable_t kernel_pagetable;extern char etext[];  // kernel.ld sets this to end of kernel code.extern char trampoline[]; // trampoline.S//該函數(shù)創(chuàng)建一個直接映射的內(nèi)核頁表,并將硬件設備、
//內(nèi)核代碼和數(shù)據(jù)段、以及跳板頁(trampoline)映射到內(nèi)核頁表中。
void
kvminit()
{kernel_pagetable = (pagetable_t) kalloc();memset(kernel_pagetable, 0, PGSIZE);// uart registerskvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W);// virtio mmio disk interfacekvmmap(VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);// CLINTkvmmap(CLINT, CLINT, 0x10000, PTE_R | PTE_W);// PLICkvmmap(PLIC, PLIC, 0x400000, PTE_R | PTE_W);// map kernel text executable and read-only.kvmmap(KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);// map kernel data and the physical RAM we'll make use of.kvmmap((uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W);// map the trampoline for trap entry/exit to// the highest virtual address in the kernel.kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
}//該函數(shù)切換硬件頁表寄存器到內(nèi)核頁表,并啟用分頁。
void
kvminithart()
{w_satp(MAKE_SATP(kernel_pagetable));sfence_vma();
}//該函數(shù)在頁表中查找虛擬地址va對應的頁表項(PTE),如果alloc非零,則在需要時分配頁表頁
pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc)
{if(va >= MAXVA)panic("walk");for(int level = 2; level > 0; level--) {pte_t *pte = &pagetable[PX(level, va)];if(*pte & PTE_V) {pagetable = (pagetable_t)PTE2PA(*pte);} else {if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)return 0;memset(pagetable, 0, PGSIZE);*pte = PA2PTE(pagetable) | PTE_V;}}return &pagetable[PX(0, va)];
}//該函數(shù)查找虛擬地址va對應的物理地址,如果未映射則返回0。只能用于查找用戶頁。
uint64
walkaddr(pagetable_t pagetable, uint64 va)
{pte_t *pte;uint64 pa;if(va >= MAXVA)return 0;pte = walk(pagetable, va, 0);if(pte == 0)return 0;if((*pte & PTE_V) == 0)return 0;if((*pte & PTE_U) == 0)return 0;pa = PTE2PA(*pte);return pa;
}//該函數(shù)在內(nèi)核頁表中添加一個映射。在啟動時使用,不刷新TLB或啟用分頁。
void
kvmmap(uint64 va, uint64 pa, uint64 sz, int perm)
{if(mappages(kernel_pagetable, va, sz, pa, perm) != 0)panic("kvmmap");
}//該函數(shù)將內(nèi)核虛擬地址轉(zhuǎn)換為物理地址。假設va是頁對齊的。
uint64
kvmpa(uint64 va)
{uint64 off = va % PGSIZE;pte_t *pte;uint64 pa;pte = walk(kernel_pagetable, va, 0);if(pte == 0)panic("kvmpa");if((*pte & PTE_V) == 0)panic("kvmpa");pa = PTE2PA(*pte);return pa+off;
}//這段代碼實現(xiàn)了mappages函數(shù),用于創(chuàng)建頁表條目(PTE),將虛擬地址映射到物理地址。
//函數(shù)接受頁表指針、虛擬地址、映射大小、物理地址和權(quán)限作為參數(shù),并返回成功或失敗的狀態(tài)。
int
mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
{uint64 a, last;pte_t *pte;a = PGROUNDDOWN(va);                      // 向下對齊虛擬地址到頁邊界last = PGROUNDDOWN(va + size - 1);        // 向下對齊最后一個虛擬地址到頁邊界for(;;){if((pte = walk(pagetable, a, 1)) == 0)  // 獲取或創(chuàng)建對應虛擬地址的PTEreturn -1;if(*pte & PTE_V)                        // 檢查PTE是否有效,防止重復映射panic("remap");*pte = PA2PTE(pa) | perm | PTE_V;       // 設置PTE,映射到物理地址并賦予權(quán)限if(a == last)                           // 如果已經(jīng)處理完最后一個頁break;a += PGSIZE;                            // 前進到下一個頁pa += PGSIZE;                           // 更新物理地址}return 0;
}//這段代碼實現(xiàn)了uvmunmap函數(shù),用于取消虛擬地址到物理地址的映射。
//函數(shù)接受頁表指針、虛擬地址、要取消映射的頁數(shù)和一個標志位作為參數(shù),
//標志位決定是否釋放物理內(nèi)存。
void
uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
{uint64 a;pte_t *pte;if((va % PGSIZE) != 0)  // 檢查虛擬地址是否對齊到頁邊界panic("uvmunmap: not aligned");for(a = va; a < va + npages * PGSIZE; a += PGSIZE){  // 遍歷每一個頁if((pte = walk(pagetable, a, 0)) == 0)  // 獲取對應虛擬地址的PTEpanic("uvmunmap: walk");if((*pte & PTE_V) == 0)  // 檢查PTE是否有效panic("uvmunmap: not mapped");if(PTE_FLAGS(*pte) == PTE_V)  // 檢查PTE是否為葉子節(jié)點panic("uvmunmap: not a leaf");if(do_free){  // 如果需要釋放物理內(nèi)存uint64 pa = PTE2PA(*pte);kfree((void*)pa);  // 釋放物理內(nèi)存}*pte = 0;  // 取消映射}
}//用于創(chuàng)建一個空的用戶頁表。函數(shù)通過分配一頁物理內(nèi)存來存儲頁表,
//并初始化該頁表。如果內(nèi)存分配失敗,函數(shù)返回0
pagetable_t
uvmcreate()
{pagetable_t pagetable;// 分配一頁物理內(nèi)存用于存儲頁表pagetable = (pagetable_t) kalloc();if(pagetable == 0)return 0;memset(pagetable, 0, PGSIZE);return pagetable;
}//用于將用戶初始化代碼加載到頁表的地址0處。此函數(shù)通常在創(chuàng)建第一個
//用戶進程時使用。代碼執(zhí)行了內(nèi)存分配、內(nèi)存映射和數(shù)據(jù)拷貝的操作
void
uvminit(pagetable_t pagetable, uchar *src, uint sz)
{char *mem;// 檢查大小是否超過一頁if(sz >= PGSIZE)panic("inituvm: more than a page");// 分配一頁物理內(nèi)存并清零mem = kalloc();memset(mem, 0, PGSIZE);// 將分配的物理內(nèi)存映射到虛擬地址0mappages(pagetable, 0, PGSIZE, (uint64)mem, PTE_W|PTE_R|PTE_X|PTE_U);// 將初始化代碼拷貝到分配的物理內(nèi)存memmove(mem, src, sz);
}//用于為進程分配頁表條目和物理內(nèi)存,以將進程的內(nèi)存從oldsz
//增長到newsz。如果分配成功,函數(shù)返回新大小;如果出錯,則返回0
uint64
uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
{char *mem;uint64 a;// 如果newsz小于oldsz,不進行任何操作,返回oldszif(newsz < oldsz)return oldsz;// 將oldsz向上取整到頁邊界oldsz = PGROUNDUP(oldsz);// 從oldsz增長到newsz,按頁分配內(nèi)存for(a = oldsz; a < newsz; a += PGSIZE){// 分配一頁物理內(nèi)存mem = kalloc();if(mem == 0){// 分配失敗,釋放之前分配的內(nèi)存uvmdealloc(pagetable, a, oldsz);return 0;}// 清零已分配的內(nèi)存memset(mem, 0, PGSIZE);// 將物理內(nèi)存映射到虛擬地址if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){// 映射失敗,釋放已分配的內(nèi)存kfree(mem);uvmdealloc(pagetable, a, oldsz);return 0;}}// 分配成功,返回newszreturn newsz;
}//用于釋放進程的用戶頁,使其內(nèi)存大小從oldsz減少到newsz。無論oldsz是否
//大于實際進程大小,或者newsz是否小于oldsz,函數(shù)都會按需要進行內(nèi)存釋放,
//并返回新的進程大小。
uint64
uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
{// 如果newsz大于等于oldsz,不需要做任何操作,返回oldszif(newsz >= oldsz)return oldsz;// 如果newsz向上取整后的頁數(shù)小于oldsz向上取整后的頁數(shù),說明需要釋放一些頁if(PGROUNDUP(newsz) < PGROUNDUP(oldsz)){int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE;uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1);}// 返回新的進程大小newszreturn newsz;
}//用于遞歸地釋放頁表頁。該函數(shù)假定所有葉子映射(即實際映射到物理內(nèi)存的頁)
//已經(jīng)被移除,因此它只需要處理非葉子頁表條目。
void
freewalk(pagetable_t pagetable)
{// 頁表中有2^9 = 512個頁表條目for(int i = 0; i < 512; i++){pte_t pte = pagetable[i];// 如果當前條目有效且不是葉子條目if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){// 該PTE指向一個更低級別的頁表uint64 child = PTE2PA(pte);// 遞歸釋放更低級別的頁表freewalk((pagetable_t)child);// 將當前條目清零pagetable[i] = 0;} else if(pte & PTE_V){// 如果當前條目是葉子條目,拋出一個錯誤panic("freewalk: leaf");}}// 釋放當前頁表kfree((void*)pagetable);
}//用于釋放用戶內(nèi)存頁,然后釋放頁表頁
void
uvmfree(pagetable_t pagetable, uint64 sz)
{if(sz > 0)uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1);freewalk(pagetable);
}//將父進程的內(nèi)存復制到子進程的頁表中,包括復制頁表項和物理內(nèi)存。
//它在成功時返回0,在失敗時返回-1,并在失敗時釋放已經(jīng)分配的所有資源以避免內(nèi)存泄漏
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
{pte_t *pte;uint64 pa, i;uint flags;char *mem;for(i = 0; i < sz; i += PGSIZE){if((pte = walk(old, i, 0)) == 0)panic("uvmcopy: pte should exist");if((*pte & PTE_V) == 0)panic("uvmcopy: page not present");pa = PTE2PA(*pte);flags = PTE_FLAGS(*pte);if((mem = kalloc()) == 0)goto err;memmove(mem, (char*)pa, PGSIZE);if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){kfree(mem);goto err;}}return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1;
}// 將一個頁表項標記為用戶不可訪問。
// 在執(zhí)行程序加載時用于用戶棧的保護頁。
void
uvmclear(pagetable_t pagetable, uint64 va)
{pte_t *pte;// 查找給定頁表(pagetable)中虛擬地址 'va' 對應的頁表項(PTE)。pte = walk(pagetable, va, 0);// 如果找不到頁表項(pte為NULL),則發(fā)生panic,表示出現(xiàn)了錯誤。if(pte == 0)panic("uvmclear");// 清除頁表項中的用戶訪問位(PTE_U)。// 這樣標記該頁為用戶不可訪問。*pte &= ~PTE_U;
}// 從內(nèi)核空間復制到用戶空間。
// 將長度為len的數(shù)據(jù)從src復制到給定頁表中虛擬地址dstva處。
// 成功時返回0,出錯時返回-1。
int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{uint64 n, va0, pa0;while(len > 0){// 對目標虛擬地址進行頁面對齊。va0 = PGROUNDDOWN(dstva);// 獲取va0對應的物理地址。pa0 = walkaddr(pagetable, va0);// 如果物理地址為0,則返回-1,表示出錯。if(pa0 == 0)return -1;// 計算當前頁內(nèi)剩余空間長度。n = PGSIZE - (dstva - va0);// 如果剩余長度大于要復制的數(shù)據(jù)長度,取要復制的數(shù)據(jù)長度。if(n > len)n = len;// 將數(shù)據(jù)從src復制到物理地址pa0 + (dstva - va0)處,長度為n。memmove((void *)(pa0 + (dstva - va0)), src, n);// 更新剩余數(shù)據(jù)長度、源地址和目標虛擬地址。len -= n;src += n;dstva = va0 + PGSIZE;}return 0;
}// 從用戶空間復制到內(nèi)核空間。
// 將長度為len的數(shù)據(jù)從給定頁表中虛擬地址srcva處復制到目標地址dst。
// 成功時返回0,出錯時返回-1。
int
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
{uint64 n, va0, pa0;while(len > 0){// 對源虛擬地址進行頁面對齊。va0 = PGROUNDDOWN(srcva);// 獲取va0對應的物理地址。pa0 = walkaddr(pagetable, va0);// 如果物理地址為0,則返回-1,表示出錯。if(pa0 == 0)return -1;// 計算當前頁內(nèi)剩余空間長度。n = PGSIZE - (srcva - va0);// 如果剩余長度大于要復制的數(shù)據(jù)長度,取要復制的數(shù)據(jù)長度。if(n > len)n = len;// 將數(shù)據(jù)從物理地址pa0 + (srcva - va0)處復制到目標地址dst,長度為n。memmove(dst, (void *)(pa0 + (srcva - va0)), n);// 更新剩余數(shù)據(jù)長度、目標地址和源虛擬地址。len -= n;dst += n;srcva = va0 + PGSIZE;}return 0;
}// 從用戶空間復制空結(jié)尾字符串到內(nèi)核空間。
// 從給定頁表中虛擬地址srcva處復制最多max字節(jié)的數(shù)據(jù)到目標地址dst,
// 直到遇到'\0'結(jié)束,或者達到max字節(jié)。
// 成功時返回0,出錯時返回-1。
int
copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
{uint64 n, va0, pa0;int got_null = 0; // 標記是否遇到了'\0'while(got_null == 0 && max > 0){// 對源虛擬地址進行頁面對齊。va0 = PGROUNDDOWN(srcva);// 獲取va0對應的物理地址。pa0 = walkaddr(pagetable, va0);if(pa0 == 0)return -1;// 計算當前頁內(nèi)剩余空間長度。n = PGSIZE - (srcva - va0);if(n > max)n = max;// 將物理地址轉(zhuǎn)換為char指針,從中復制數(shù)據(jù)直到遇到'\0'或者達到max長度。char *p = (char *) (pa0 + (srcva - va0));while(n > 0){if(*p == '\0'){ // 如果遇到了'\0',復制結(jié)束。*dst = '\0';got_null = 1;break;} else { // 否則繼續(xù)復制字符。*dst = *p;}--n;--max;p++;dst++;}srcva = va0 + PGSIZE; // 更新源虛擬地址為下一頁的起始地址。}if(got_null){return 0; // 復制成功,返回0。} else {return -1; // 復制失敗(未遇到'\0'但已達到max長度),返回-1。}
}

3.kernel/kalloc.c?

這段代碼實現(xiàn)了一個物理內(nèi)存分配器,用于用戶進程、內(nèi)核棧、頁表頁以及管道緩沖區(qū)。它主要負責分配和釋放4096字節(jié)的頁面(頁)。

// Physical memory allocator, for user processes,
// kernel stacks, page-table pages,
// and pipe buffers. Allocates whole 4096-byte pages.#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "spinlock.h"
#include "riscv.h"
#include "defs.h"void freerange(void *pa_start, void *pa_end);extern char end[]; // first address after kernel.// defined by kernel.ld.//run結(jié)構(gòu)體定義了一個單向鏈表節(jié)點,用于維護空閑物理內(nèi)存頁的鏈表。
struct run {struct run *next;
};//kmem結(jié)構(gòu)體包含一個自旋鎖和一個空閑內(nèi)存頁鏈表的頭指針,
//用于實現(xiàn)線程安全的內(nèi)存管理。
struct {struct spinlock lock;struct run *freelist;
} kmem;//該函數(shù)初始化物理內(nèi)存分配器。它首先初始化自旋鎖,然后調(diào)用freerange函數(shù),
//將從內(nèi)核結(jié)束地址(end)到物理內(nèi)存頂部(PHYSTOP)之間的內(nèi)存頁加入空閑列表。
void
kinit()
{initlock(&kmem.lock, "kmem");freerange(end, (void*)PHYSTOP);
}//該函數(shù)將從pa_start到pa_end范圍內(nèi)的內(nèi)存頁加入空閑列表。
//它首先將pa_start地址向上對齊到頁邊界,然后逐頁調(diào)用kfree函數(shù)釋放這些內(nèi)存頁。
void
freerange(void *pa_start, void *pa_end)
{char *p;p = (char*)PGROUNDUP((uint64)pa_start);for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE)kfree(p);
}//該函數(shù)釋放一個物理內(nèi)存頁,將其加入空閑列表。它首先檢查pa是否是頁對齊的,
//并且在合法范圍內(nèi)。然后用垃圾數(shù)據(jù)填充該頁,防止懸空引用。最后將該頁加入空閑列表,
//使用自旋鎖確保線程安全。
void
kfree(void *pa)
{struct run *r;if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)panic("kfree");// Fill with junk to catch dangling refs.memset(pa, 1, PGSIZE);r = (struct run*)pa;acquire(&kmem.lock);r->next = kmem.freelist;kmem.freelist = r;release(&kmem.lock);
}//該函數(shù)分配一個物理內(nèi)存頁。它從空閑列表中取出一個頁,
//如果成功分配,則用垃圾數(shù)據(jù)填充該頁。返回頁的地址,如果分配失敗則返回0。
void *
kalloc(void)
{struct run *r;acquire(&kmem.lock);r = kmem.freelist;if(r)kmem.freelist = r->next;release(&kmem.lock);if(r)memset((char*)r, 5, PGSIZE); // fill with junkreturn (void*)r;
}
http://www.risenshineclean.com/news/51014.html

相關(guān)文章:

  • 有哪個網(wǎng)站可以做口腔執(zhí)業(yè)助理醫(yī)師題庫互聯(lián)網(wǎng)營銷師培訓課程
  • 現(xiàn)在網(wǎng)站建設還用測瀏覽器嗎企業(yè)培訓課程安排表
  • 有多少網(wǎng)站是做廢舊信息的edm營銷
  • 深圳做企業(yè)網(wǎng)站的公北京搜索引擎優(yōu)化
  • 網(wǎng)站為什么續(xù)費域名停靠瀏覽器
  • app產(chǎn)品網(wǎng)站建設沈陽線上教學
  • 制作視頻網(wǎng)站教程網(wǎng)站測速工具
  • 廣州建網(wǎng)站培訓刷粉網(wǎng)站推廣馬上刷
  • 做國外購物網(wǎng)站網(wǎng)上怎么找人去推廣廣告
  • 站長素材網(wǎng)站種子搜索神器在線引擎
  • 邯鄲網(wǎng)站優(yōu)化平臺fifa最新排名出爐
  • 手機網(wǎng)站制作合同如何聯(lián)系百度推廣
  • 什么是網(wǎng)站維護寧波優(yōu)化系統(tǒng)
  • 網(wǎng)站如何做seo的網(wǎng)絡營銷課程培訓機構(gòu)
  • 無錫知名網(wǎng)站制作求職seo
  • html5手機網(wǎng)站特效今日山東新聞頭條
  • 麥包包的網(wǎng)站建設網(wǎng)絡運營推廣
  • 英文網(wǎng)站源碼北京疫情又嚴重了
  • 如何建設網(wǎng)站設計網(wǎng)站軟件推薦
  • 柳州建站免費seo視頻教程
  • 自學做網(wǎng)站界面百度自動駕駛技術(shù)
  • 中國建設銀行網(wǎng)站u盾修改密碼seo自學網(wǎng)app
  • 自動優(yōu)化網(wǎng)站建設服裝市場調(diào)研報告范文
  • 可口可樂公司建設網(wǎng)站的目的是什么seo推廣優(yōu)化工具
  • 鄭州網(wǎng)站建設zzjisu網(wǎng)絡軟文營銷案例3篇
  • 學校網(wǎng)站源碼php地推團隊接單平臺
  • phpcms v9 網(wǎng)站搬家軟件培訓機構(gòu)排名
  • 開源展示型網(wǎng)站沈陽seo優(yōu)化新勢力
  • 網(wǎng)站建設推廣選stso88效果好91關(guān)鍵詞
  • 專業(yè)做網(wǎng)站的技術(shù)人員百度網(wǎng)站如何優(yōu)化排名