当前位置:   article > 正文

内核级命令实现示例_内核态运行的指令

内核态运行的指令

问题

内核级命令如何实现?

通过系统调用

内核级命令的本质

命令所对应的功能需要内核协助才能实现

  • 在内核中实现命令的功能 (如:获取硬件信息)
  • 创建系统调用接口连接内核功能
  • Shell 任务通过系统调用实现命令

命令示例:获取系统物理内存容量 (mem)

解决方案

1. 在系统启动时,在实模式下获取物理内存容量 (int 0x15)

2. 将物理内存容量暂存于共享内存区

3. 内核执行时,从共享内存区获取物理内存容量 (存入全局变量)

4. 实现系统调用 uint GetMemSize()

5. Shell 任务通过 uint GetMemSize() 实现命令 mem 并打印容量大小

物理内存容量大小获取 (回顾)

物理内存容量大小修正 (回顾)

uint GetMemSize() 的实现

mem 命令的实现

 

内核级命令的实现

common.asm

  1. BaseOfSharedMemory equ 0xA000
  2. ; Shared Value Address
  3. GdtEntry equ BaseOfSharedMemory + 0
  4. GdtSize equ BaseOfSharedMemory + 4
  5. IdtEntry equ BaseOfSharedMemory + 8
  6. IdtSize equ BaseOfSharedMemory + 12
  7. RunTaskEntry equ BaseOfSharedMemory + 16
  8. InitInterruptEntry equ BaseOfSharedMemory + 20
  9. MemSize equ BaseOfSharedMemory + 24
  10. SendEOIEntry equ BaseOfSharedMemory + 28
  11. LoadTaskEntry equ BaseOfSharedMemory + 32
  12. AppMainEntry equ BaseOfSharedMemory + 36

loader.asm

  1. ;
  2. ;
  3. GetMemSize:
  4. mov dword [MemSize], 0
  5. xor eax, eax
  6. mov ax, 0xE801
  7. int 0x15
  8. jc geterr
  9. shl eax, 10 ; eax = eax * 1024
  10. shl ebx, 6 + 10 ; ebx = ebx * 64 * 1024
  11. mov ecx, 1
  12. shl ecx, 20 ; ecx = 1024 * 1024
  13. add dword[MemSize], eax
  14. add dword[MemSize], ebx
  15. add dword[MemSize], ecx
  16. jmp getok
  17. geterr:
  18. mov dword [MemSize], 0
  19. getok:
  20. ret

kentry.asm

  1. ;
  2. ;
  3. InitGlobal:
  4. push ebp
  5. mov ebp, esp
  6. mov eax, dword [GdtEntry]
  7. mov [gGdtInfo], eax
  8. mov eax, dword [GdtSize]
  9. mov [gGdtInfo + 4], eax
  10. mov eax, dword [IdtEntry]
  11. mov [gIdtInfo], eax
  12. mov eax, dword [IdtSize]
  13. mov [gIdtInfo + 4], eax
  14. mov eax, dword [RunTaskEntry]
  15. mov dword [RunTask], eax
  16. mov eax, dword [InitInterruptEntry]
  17. mov dword [InitInterrupt], eax
  18. mov eax, dword [SendEOIEntry]
  19. mov dword [SendEOI], eax
  20. mov eax, dword [LoadTaskEntry]
  21. mov dword [LoadTask], eax
  22. mov eax, dword [MemSize]
  23. mov dword [gMemSize], eax
  24. leave
  25. ret

syscall.c

  1. uint GetMemSize()
  2. {
  3. uint ret = 0;
  4. SysCall(3, 0, &ret, 0);
  5. return ret;
  6. }

ihandler.c

  1. void SysCallHandler(uint type, uint cmd, uint param1, uint param2) // __cdcel__
  2. {
  3. switch(type)
  4. {
  5. case 0:
  6. TaskCallHandler(cmd, param1, param2);
  7. break;
  8. case 1:
  9. MutexCallHandler(cmd, param1, param2);
  10. break;
  11. case 2:
  12. KeyCallHandler(cmd, param1, param2);
  13. case 3:
  14. SysInfoHandler(cmd, param1, param2);
  15. break;
  16. default:
  17. break;
  18. }
  19. }

sysinfo.c

  1. uint gMemSize = 0;
  2. void SysInfoHandler(uint cmd, uint param1, uint param2)
  3. {
  4. if(cmd == 0)
  5. {
  6. uint* pRet = (uint*)param1;
  7. *pRet = gMemSize;
  8. }
  9. }

shell.c

  1. static void Mem()
  2. {
  3. uint ms = GetMemSize() >> 20;
  4. ClearCmdInfo();
  5. SetPrintPos(CMD_START_W, CMD_START_H + 1);
  6. PrintString("Physical Memory: ");
  7. PrintIntDec(ms);
  8. PrintString(" MB\n");
  9. }
  10. void Shell()
  11. {
  12. List_Init(&gCmdList);
  13. AddCmdEntry("clear", Clear);
  14. AddCmdEntry("demo1", Demo1);
  15. AddCmdEntry("demo2", Demo2);
  16. AddCmdEntry("mem", Mem);
  17. SetPrintPos(CMD_START_W, CMD_START_H);
  18. PrintString(PROMPT);
  19. while(1)
  20. {
  21. uint key = ReadKey();
  22. if(IsKeyDown(key))
  23. {
  24. char ch = GetChar(key);
  25. byte vc = GetKeyCode(key);
  26. Handler(ch, vc);
  27. }
  28. }
  29. }

GetMemSize 函数中获取到的内存容量的单位为 Byte,我们把它显示为 MB,所以需要将获取到的内存大小右移20位。

执行 mem 命令结果如下图所示

 该系统中物理内存大小为 128MB

小结

Shell 的本质是一个任务 (执行于用户态)

Shell 是命令解释器,解释用户输入的命令

Shell 命令可分为3种类型:

  • 启动型命令:启动其他任务 (一个或多个) 实现功能
  • 应用级命令:Shell 任务自身实现命令功能
  • 内核级命令:Shell 任务依赖内核实现命令功能
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/476441
推荐阅读
相关标签
  

闽ICP备14008679号