自己学习的备忘,从笔记转移过来,后面每一项写一篇对应的理解文章
内核线程和用户进程异同记录
- 所有进程的内核地址空间则都是一样的。对于内核进程,由于其始终运行在内核态,所以没有用户地址空间,其对应的tast_struct结构体中的mm域也就被赋值为NULL。而堆的概念应该是只存在于进程的用户地址空间中,所以内核进程是没有堆一说的。
- 内核线程只工作在内核态中;而用户线程则既可以运行在内核态,也可以运行在用户态; 内核线程没有用户空间,所以对于一个内核线程来说,它的0-3G的内存空间是空白的,它的current->mm是空的,与内核使用同一张页表;而用户线程则可以看到完整的0-4G内存空间。
- 杀死内核线程:将该task_struct的状态标志位改为 KTHREAD_SHOULD_STOP (调kthread_stop函数),内核线程忽略信号,可见 IT虾米网
- 守护进程可被信号杀死,父进程ID为1,内核进程父进程ID为2(kthreadd)
内核空间分布和寻址
-
这里写得挺详细:IT虾米网
- 分 ZONE_DMA(16M), ZONE_NORMAL(16M-896M), ZONE_HIGHMEN(896M-1G)(32位机器), ZONE_NORMAL 和 ZONE_DMA 直接映射物理内存,ZONE_HIGHMEM 通过内核PTE页面建立映射,临时用,用完后归还
- 进程寻址空间0-4G,进程只有进入内核态才能访问3G-4G
- 进程通过系统调用进入内核态
- 每个进程虚拟空间的3G~4G部分是相同的
- 进程从用户态进入内核态不会引起CR3的改变但会引起堆栈的改变
-
从用户态进入内核态过程(门的判断)
- 图参考这里:IT虾米网
- CPU特权级切换(CPL):是取的CS寄存器的低两位,在任何时候,不管CPU内部正在发生什么,只要看一眼cs中的CPL,你就可以知道此刻的特权级了。
- 防止用户态访问内核态空间
- 通过分段保护机制,当 RPL 和 CPL 都大于 DPL 时候才可以访问对应地址的内存
- CPL是当前进程的权限级别(Current Privilege Level),是当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位。
- DPL:描述符特权(Descriptor Privilege Level) 存储在描述符中的权限位,用于描述代码的所属的特权等级,也就是代码本身真正的特权级。一个程序可以使用多个段(Data,Code,Stack)也可以只用一个code段等。正常的情况下,当程序的环境建立好后,段描述符都不需要改变——当然DPL也不需要改变,因此每个段的DPL值是固定。
- RPL:请求特权级RPL(Request Privilege Level) ,RPL保存在选择子的最低两位。RPL说明的是进程对段访问的请求权限,意思是当前进程想要的请求权限。RPL的值由程序员自己来自由的设置,并不一定RPL>=CPL,但是当RPL<CPL时,实际起作用的就是CPL了,因为访问时的特权检查是判断:EPL=max(RPL,CPL)<=DPL是否成立,所以RPL可以看成是每次访问时的附加限制,RPL=0时附加限制最小,RPL=3时附加限制最大。所以你不要想通过来随便设置一个rpl来访问一个比cpl更内层的段。
- 通过分段保护机制,当 RPL 和 CPL 都大于 DPL 时候才可以访问对应地址的内存
-
用户态到内核态切换途径
- 系统调用
- 中断
- 异常
-
用户态进入内核态后进程栈如何切换
- 详细代码参考这里:IT虾米网
- 读取TSS段(保存有用户栈顶指针和内核栈顶指针)读取 sp0, ss0
// TSS 结构定义(参考) #ifdef CONFIG_X86_32 /* This is the TSS defined by the hardware. */ struct x86_hw_tss { unsigned short back_link, __blh; unsigned long sp0; //当前进程的内核栈顶指针 unsigned short ss0, __ss0h; //当前进程的内核栈段描述符 unsigned long sp1; /* ss1 caches MSR_IA32_SYSENTER_CS: */ unsigned short ss1, __ss1h; unsigned long sp2; unsigned short ss2, __ss2h; unsigned long __cr3; unsigned long ip; unsigned long flags; unsigned long ax; unsigned long cx; unsigned long dx; unsigned long bx; unsigned long sp; //当前进程用户态栈顶指针 unsigned long bp; unsigned long si; unsigned long di; unsigned short es, __esh; unsigned short cs, __csh; unsigned short ss, __ssh; unsigned short ds, __dsh; unsigned short fs, __fsh; unsigned short gs, __gsh; unsigned short ldt, __ldth; unsigned short trace; unsigned short io_bitmap_base; } __attribute__((packed));
转载于:https://www.cnblogs.com/varXinYuan/p/10865443.html