首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

《操作系统真象还原》第9~10章+鼠标驱动源代码

操作系统 90.68KB 18 需要积分: 1
立即下载

资源介绍:

和《操作系统真象还原》第9~10章+鼠标驱动的报告配套
#include "memory.h" #include "bitmap.h" #include "stdint.h" #include "global.h" #include "debug.h" #include "print.h" #include "string.h" #define PG_SIZE 4096 /*************** 位图地址 ******************** * 因为0xc009f000是内核主线程栈顶,0xc009e000是内核主线程的pcb. * 一个页框大小的位图可表示128M内存, 位图位置安排在地址0xc009a000, * 这样本系统最大支持4个页框的位图,即512M */ #define MEM_BITMAP_BASE 0xc009a000 /*************************************/ #define PDE_IDX(addr) ((addr & 0xffc00000) >> 22) #define PTE_IDX(addr) ((addr & 0x003ff000) >> 12) /* 0xc0000000是内核从虚拟地址3G起. 0x100000意指跨过低端1M内存,使虚拟地址在逻辑上连续 */ #define K_HEAP_START 0xc0100000 /* 内存池结构,生成两个实例用于管理内核内存池和用户内存池 */ struct pool { struct bitmap pool_bitmap; // 本内存池用到的位图结构,用于管理物理内存 uint32_t phy_addr_start; // 本内存池所管理物理内存的起始地址 uint32_t pool_size; // 本内存池字节容量 }; struct pool kernel_pool, user_pool; // 生成内核内存池和用户内存池 struct virtual_addr kernel_vaddr; // 此结构是用来给内核分配虚拟地址 /* 在pf表示的虚拟内存池中申请pg_cnt个虚拟页, * 成功则返回虚拟页的起始地址, 失败则返回NULL */ static void* vaddr_get(enum pool_flags pf, uint32_t pg_cnt) { int vaddr_start = 0, bit_idx_start = -1; uint32_t cnt = 0; if (pf == PF_KERNEL) { bit_idx_start = bitmap_scan(&kernel_vaddr.vaddr_bitmap, pg_cnt); if (bit_idx_start == -1) { return NULL; } while(cnt < pg_cnt) { bitmap_set(&kernel_vaddr.vaddr_bitmap, bit_idx_start + cnt++, 1); } vaddr_start = kernel_vaddr.vaddr_start + bit_idx_start * PG_SIZE; } else { // 用户内存池,将来实现用户进程再补充 } return (void*)vaddr_start; } /* 得到虚拟地址vaddr对应的pte指针*/ uint32_t* pte_ptr(uint32_t vaddr) { /* 先访问到页表自己 + \ * 再用页目录项pde(页目录内页表的索引)做为pte的索引访问到页表 + \ * 再用pte的索引做为页内偏移*/ uint32_t* pte = (uint32_t*)(0xffc00000 + \ ((vaddr & 0xffc00000) >> 10) + \ PTE_IDX(vaddr) * 4); return pte; } /* 得到虚拟地址vaddr对应的pde的指针 */ uint32_t* pde_ptr(uint32_t vaddr) { /* 0xfffff是用来访问到页表本身所在的地址 */ uint32_t* pde = (uint32_t*)((0xfffff000) + PDE_IDX(vaddr) * 4); return pde; } /* 在m_pool指向的物理内存池中分配1个物理页, * 成功则返回页框的物理地址,失败则返回NULL */ static void* palloc(struct pool* m_pool) { /* 扫描或设置位图要保证原子操作 */ int bit_idx = bitmap_scan(&m_pool->pool_bitmap, 1); // 找一个物理页面 if (bit_idx == -1 ) { return NULL; } bitmap_set(&m_pool->pool_bitmap, bit_idx, 1); // 将此位bit_idx置1 uint32_t page_phyaddr = ((bit_idx * PG_SIZE) + m_pool->phy_addr_start); return (void*)page_phyaddr; } /* 页表中添加虚拟地址_vaddr与物理地址_page_phyaddr的映射 */ static void page_table_add(void* _vaddr, void* _page_phyaddr) { uint32_t vaddr = (uint32_t)_vaddr, page_phyaddr = (uint32_t)_page_phyaddr; uint32_t* pde = pde_ptr(vaddr); uint32_t* pte = pte_ptr(vaddr); /************************ 注意 ************************* * 执行*pte,会访问到空的pde。所以确保pde创建完成后才能执行*pte, * 否则会引发page_fault。因此在*pde为0时,*pte只能出现在下面else语句块中的*pde后面。 * *********************************************************/ /* 先在页目录内判断目录项的P位,若为1,则表示该表已存在 */ if (*pde & 0x00000001) { // 页目录项和页表项的第0位为P,此处判断目录项是否存在 ASSERT(!(*pte & 0x00000001)); if (!(*pte & 0x00000001)) { // 只要是创建页表,pte就应该不存在,多判断一下放心 *pte = (page_phyaddr | PG_US_U | PG_RW_W | PG_P_1); // US=1,RW=1,P=1 } else { //应该不会执行到这,因为上面的ASSERT会先执行。 PANIC("pte repeat"); *pte = (page_phyaddr | PG_US_U | PG_RW_W | PG_P_1); // US=1,RW=1,P=1 } } else { // 页目录项不存在,所以要先创建页目录再创建页表项. /* 页表中用到的页框一律从内核空间分配 */ uint32_t pde_phyaddr = (uint32_t)palloc(&kernel_pool); *pde = (pde_phyaddr | PG_US_U | PG_RW_W | PG_P_1); /* 分配到的物理页地址pde_phyaddr对应的物理内存清0, * 避免里面的陈旧数据变成了页表项,从而让页表混乱. * 访问到pde对应的物理地址,用pte取高20位便可. * 因为pte是基于该pde对应的物理地址内再寻址, * 把低12位置0便是该pde对应的物理页的起始*/ memset((void*)((int)pte & 0xfffff000), 0, PG_SIZE); ASSERT(!(*pte & 0x00000001)); *pte = (page_phyaddr | PG_US_U | PG_RW_W | PG_P_1); // US=1,RW=1,P=1 } } /* 分配pg_cnt个页空间,成功则返回起始虚拟地址,失败时返回NULL */ void* malloc_page(enum pool_flags pf, uint32_t pg_cnt) { ASSERT(pg_cnt > 0 && pg_cnt < 3840); /*********** malloc_page的原理是三个动作的合成: *********** 1通过vaddr_get在虚拟内存池中申请虚拟地址 2通过palloc在物理内存池中申请物理页 3通过page_table_add将以上得到的虚拟地址和物理地址在页表中完成映射 ***************************************************************/ void* vaddr_start = vaddr_get(pf, pg_cnt); if (vaddr_start == NULL) { return NULL; } uint32_t vaddr = (uint32_t)vaddr_start, cnt = pg_cnt; struct pool* mem_pool = pf & PF_KERNEL ? &kernel_pool : &user_pool; /* 因为虚拟地址是连续的,但物理地址可以是不连续的,所以逐个做映射*/ while (cnt-- > 0) { void* page_phyaddr = palloc(mem_pool); if (page_phyaddr == NULL) { // 失败时要将曾经已申请的虚拟地址和物理页全部回滚,在将来完成内存回收时再补充 return NULL; } page_table_add((void*)vaddr, page_phyaddr); // 在页表中做映射 vaddr += PG_SIZE; // 下一个虚拟页 } return vaddr_start; } /* 从内核物理内存池中申请pg_cnt页内存,成功则返回其虚拟地址,失败则返回NULL */ void* get_kernel_pages(uint32_t pg_cnt) { void* vaddr = malloc_page(PF_KERNEL, pg_cnt); if (vaddr != NULL) { // 若分配的地址不为空,将页框清0后返回 memset(vaddr, 0, pg_cnt * PG_SIZE); } return vaddr; } /* 初始化内存池 */ static void mem_pool_init(uint32_t all_mem) { put_str(" mem_pool_init start\n"); uint32_t page_table_size = PG_SIZE * 256; // 页表大小= 1页的页目录表+第0和第768个页目录项指向同一个页表+ // 第769~1022个页目录项共指向254个页表,共256个页框 uint32_t used_mem = page_table_size + 0x100000; // 0x100000为低端1M内存 uint32_t free_mem = all_mem - used_mem; uint16_t all_free_pages = free_mem / PG_SIZE; // 1页为4k,不管总内存是不是4k的倍数, // 对于以页为单位的内存分配策略,不足1页的内存不用考虑了。 uint16_t kernel_free_pages = all_free_pages / 2; uint16_t user_free_pages = all_free_pages - kernel_free_pages; /* 为简化位图操作,余数不处理,坏处是这样做会丢内存。 好处是不用做内存的越界检查,因为位图表示的内存少于实际物理内存*/ uint32_t kbm_length = kernel_free_pages / 8; // Kernel BitMap的长度,位图中的一位表示一页,以字节为单位 uint32_t ubm_length = user_free_pages / 8; // User BitMap的长度. uint32_t kp_start = used_mem; // Kernel Pool start,内核内存�

资源文件列表:

kbd&mou.zip 大约有71个文件
  1. kbd&mou/boot/
  2. kbd&mou/boot/include/
  3. kbd&mou/boot/include/boot.inc 2.12KB
  4. kbd&mou/boot/loader.bin 1.37KB
  5. kbd&mou/boot/loader.S 15.75KB
  6. kbd&mou/boot/mbr.bin 512B
  7. kbd&mou/boot/mbr.S 3.48KB
  8. kbd&mou/build/
  9. kbd&mou/build/bitmap.o 2.3KB
  10. kbd&mou/build/console.o 2.27KB
  11. kbd&mou/build/debug.o 1.67KB
  12. kbd&mou/build/init.o 1.48KB
  13. kbd&mou/build/interrupt.o 5.01KB
  14. kbd&mou/build/ioqueue.o 3.62KB
  15. kbd&mou/build/kernel.bin 31.55KB
  16. kbd&mou/build/kernel.map 25.39KB
  17. kbd&mou/build/kernel.o 4.27KB
  18. kbd&mou/build/keyboard.o 3.09KB
  19. kbd&mou/build/list.o 2.71KB
  20. kbd&mou/build/main.o 1.99KB
  21. kbd&mou/build/memory.o 4.71KB
  22. kbd&mou/build/mouse.o 4.12KB
  23. kbd&mou/build/print.o 1.83KB
  24. kbd&mou/build/string.o 3.81KB
  25. kbd&mou/build/switch.o 448B
  26. kbd&mou/build/sync.o 3.76KB
  27. kbd&mou/build/thread.o 6.03KB
  28. kbd&mou/build/timer.o 2.41KB
  29. kbd&mou/device/
  30. kbd&mou/device/console.c 800B
  31. kbd&mou/device/console.h 275B
  32. kbd&mou/device/ioqueue.c 2.56KB
  33. kbd&mou/device/ioqueue.h 947B
  34. kbd&mou/device/keyboard.c 7.87KB
  35. kbd&mou/device/keyboard.h 122B
  36. kbd&mou/device/mouse.c 3.64KB
  37. kbd&mou/device/mouse.h 82B
  38. kbd&mou/device/timer.c 1.97KB
  39. kbd&mou/device/timer.h 98B
  40. kbd&mou/kernel/
  41. kbd&mou/kernel/debug.c 633B
  42. kbd&mou/kernel/debug.h 903B
  43. kbd&mou/kernel/global.h 942B
  44. kbd&mou/kernel/init.c 591B
  45. kbd&mou/kernel/init.h 76B
  46. kbd&mou/kernel/interrupt.c 7.61KB
  47. kbd&mou/kernel/interrupt.h 586B
  48. kbd&mou/kernel/kernel.S 2.76KB
  49. kbd&mou/kernel/main.c 1.03KB
  50. kbd&mou/kernel/memory.c 10.32KB
  51. kbd&mou/kernel/memory.h 1.07KB
  52. kbd&mou/lib/
  53. kbd&mou/lib/kernel/
  54. kbd&mou/lib/kernel/bitmap.c 2.85KB
  55. kbd&mou/lib/kernel/bitmap.h 525B
  56. kbd&mou/lib/kernel/io.h 2.15KB
  57. kbd&mou/lib/kernel/list.c 3.19KB
  58. kbd&mou/lib/kernel/list.h 1.45KB
  59. kbd&mou/lib/kernel/print.h 238B
  60. kbd&mou/lib/kernel/print.S 8.48KB
  61. kbd&mou/lib/stdint.h 322B
  62. kbd&mou/lib/string.c 3.27KB
  63. kbd&mou/lib/string.h 571B
  64. kbd&mou/lib/user/
  65. kbd&mou/makefile 4.34KB
  66. kbd&mou/thread/
  67. kbd&mou/thread/switch.S 982B
  68. kbd&mou/thread/sync.c 2.75KB
  69. kbd&mou/thread/sync.h 692B
  70. kbd&mou/thread/thread.c 6.33KB
  71. kbd&mou/thread/thread.h 3.4KB
0评论
提交 加载更多评论
其他资源 darkreader-chrome.zip 20240711发布 版本v4.9.88
来源 https://github.com/darkreader/darkreader/releases Dark Reader是一个护眼扩展程序,通过实时生成黑暗主题,为每一个网站启用夜间模式。 Dark Reader 反转明亮的颜色,使网页内容具有高对比度并易于在夜间阅读。 使用方法: 1.解压darkreader-chrome-20240711.zip到文件夹darkreader-chrome-20240711; 2.在chrome中输入地址 chrome://extensions/ 打开页面 3.开启右上角“开发者模式” 4.点击左边“加载已解压的扩展程序”,选择刚才解压出来的文件夹 5.安装完成
atlas图集分割11
11
json图集分割111
11
atlas图集分割与json图集分割
111
STM32F103C8T6 标准库模板工程
STM32F103C8T6 标准库模板工程,用于FreeRTOS标准库学习。
scala-2.xx.zip
压缩包有 scala-2.10.7.zip 和 scala-2.11.12.zip scala-2.10.7 Released November 09, 2017 https://www.scala-lang.org/download/2.10.7.html scala-2.11.12 Released November 09, 2017 https://www.scala-lang.org/download/2.11.12.html
scala-2.13.14.zip
scala-2.13.14 Released May 1, 2024 https://www.scala-lang.org/download/2.13.14.html
scala-2.12.19.zip
scala-2.12.19 Released February 26, 2024 https://www.scala-lang.org/download/2.12.19.html