处理器总处于以下状态中的一种
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;
回旋锁是解决多个CPU可重入问题
2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;
回旋锁是解决多个CPU可重入问题
回旋的时候,等待着将持续占用CPU,不睡眠
回旋锁会标识cpu id信息?
中断有CPU亲和性
3、用户态,运行于用户空间。
线程锁是解决多个线程的可重入问题
有没有程序完全运行在用户态,压根不进入内核?
如果运行当前的用户态进程,如有硬件中断,会直接进入中断上下文
用户态进入内核态通过系统调用或者中断
内核态通知用户态的方式是通过信号的机制,当用户态程序执行的系统调用返回到用户态的时候,就会检查进程是否有信号要处理
SignalPending 当前进程使用sigmask的原因,没有被接收和处理的信号, 一旦将sigmask重新设置后,这个信号就会出现了,相当于信号被挂起
用户空间的应用程序,通过系统调用,进入内核空间。
这个时候用户空间的进程要传递很多变量、参数的值给内核,内核态运行的时候也要保存用户进程的一些寄存器值、变量等。
所谓的“进程上下文”,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等。
在LINUX中,当前进程上下文均保存在进程的任务数据结构中。
硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。
这个个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。
所谓的“中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)
1、睡眠或者放弃CPU。
这样做的后果是灾难性的,因为内核在进入中断之前会关闭进程调度,
一旦睡眠或者放弃CPU,这时内核无法调度别的进程来执行,系统就会死掉
2、尝试获得信号量如果获得不到信号量,代码就会睡眠,会产生和上面相同的情况
3、执行耗时的任务 中断处理应该尽可能快,因为内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。
4、访问用户空间的虚拟地址 因为中断上下文是和特定进程无关的,它是内核代表硬件运行在内核空间,所以在中端上下文无法访问用户空间的虚拟地址
4、存在指令调度、线程调度、进程调度?
指令调度本是将指令放到不同的CPU上执行的可能, 不存在指令调度,指令的调度附属在线程调度上
在一次时间片内,当有相同的指令数据不同的线程,也运行在不同的CPU上的时候,如果这个指令序列有CPU相关性的话,就要进行回旋控制
5、多核环境下的原子性
如果cpu只能操作Cache,但是在指令中看到了基于内存地址的操作数
指令中访问的地址的数据,在指令执行的时候实际已经换成了cpu中的Cache?
隐藏在指令背后的cache,cpu执行时,只会也只能使用cache
6、线性地址到物理地址的转换
这个是tlb的任务,tlb不是用来存放cache数据,而是存放的是物理地址
这个物理地址也是页表项,页内的偏移可以直接计算
这个才是组关联、全关联、直接关联的的逻辑体现的地方
正好应了操作系统课程中说的页的换入换出,这就是所谓的cache 命中的说法
而缓存内存中的部分数据的cache可能是另外的一个东西(Mem addr->cache addr的映射)
7、内核态堆栈
不仅仅用户态存在堆栈,在内核态也需要堆栈
内核态堆栈的使用发生在系统调用、用户态发生中断时内核堆栈产生作用
用户态切换到内核态,内核态堆栈的使用方式是把用户态的堆栈地址压入内核态的堆栈
软中断的执行过程中的一些内核堆栈的使用,则不用保存用户态的堆栈
内核态的堆栈是每个进程都有一个,不是每个cpu一个