内核笔记 - 用户态
写完这篇笔记之后,我对操作系统的集中学习时间也告一段落,一个半月以来我学会了许多主要知识,像虚拟内存、物理内存、分页机制、用户态、中断等,但也有一部分没来得及学,如文件系统,多任务等,这留给我以后不断完善。
我们之前一直都在内核状态下工作,特权级处于ring0,但我们平时在Windows或Linux所运行的程序,其实都属于用户进程,它运行在ring3下,所以用户能做的事很有限,比如不能访问内核的段,不能执行特权指令(像hlt),否则病毒就可以把你的操作系统卸载,然后把它自己变成操作系统:)
为了安全考虑,操作系统提供了syscall,使用户可以受限的访问内核级功能。玩Linux的都知道,可以用int 80来调用syscall。这次我们将进入用户模式下,并写一个syscall供用户调用。
切换到用户态
switch_to_user_mode 专门用来切换模式,从内核态切换到用户态。原理也比较好理解,就是更改cs,ds,ss等寄存器的值为用户段的选择子。
1 | /* |
任务切换
在x86体系结构下想要进行任务切换,必须要用TSS,这东西说白了就是为了保护现场,每个任务都有一个。
1 | /* |
安装TSS,在GDT中安装tss描述符。
1 | /* |
更新TR寄存器:
1 | /* |
syscall
然后实现syscall,类似于Linux中的write,read,execve。
为了简单,这里只实现一个print功能的syscall。
initialise_syscalls 安装syscall的调用函数到0x80号中断。
syscall_handler 调用syscalls[regs->eax]指向的函数,这里我指向的是printk。
1 | /* |
这些宏是为了创建给用户调用的函数,比如创建一个叫syscall_printk的函数,用户只能通过调用它,然后内部会执行int 0x80,触发中断处理程序。
1 | /* |
测试
1 | /* |