1
阻塞是一种被动行为,是在请求IO资源时,发生的等待。 IO资源拿到后,自动加入就绪任务队列,等待分配CPU。
从阻塞到运行:不知道。
从就绪到阻塞:进程因为得不到io资源才进入阻塞,而请求io必须需要cpu ,所以不可能什么都不做就进入阻塞了。
2
当中断发生时,计算机会干什么?
中断硬件将现在的程序计数器,程序状态字,寄存器数值压入堆栈。(硬件)
指针跳转到中断向量表对应的中断地址的内存。(硬件)
中断向量表保存的是各个中断处理程序的地址,而跳转最终的目的地是中断处理程序的首地址。
中断服务例程接管剩余的工作:(软件)
- 保存寄存器的值至进程的表项中。
- 删除硬件保存在堆栈的第一步的信息。
- 将进程指针指向一个新的临时堆栈。
- 调用c中断服务例程。
- (typically reads and buffers input).
- 调用调度程序,决定随后运行哪个进程。
- 调用汇编语言程序,为当前进程转入寄存器值和内存映射,并启动程序。
想要使用硬件代替软件,即将第三步的1-4步变为硬件完成的。
第一步,第三步的1-2步应当合为一步:设计一种向量表,直接保存所有进程的表项的开始地址,当需要调度程序时,直接将对应的计数器和psw,寄存器数值压入。
但是,写到这里问题来了,这样子做势必会增大缓存的容量,而容量和速度不可兼得,所以cpu会花很长,很长的时间来等待程序的调度,得不偿失。
3
pg 53:一些诸如保存寄存器值和设置堆栈指针等操作,无法用c语言这类高级语言描述,所以这些操作通过一个短小的汇编语言例程完成,通常该例程可以供所有的中断使用,因为无论中断是怎样引起的,有关保存寄存器的工作则是完全一样的。
Actions such as saving the registers and setting the stack pointer cannot even be expressed in high-level languages such as C, so they are performed by a small assembly-language routine, usually the same one for all interrupts since the work of saving the registers is identical, no matter what the cause of the interrupt is.
英文版 pg 95。
4
网络上给出的答案是:
- 首先,不希望操作系统崩溃,由于某些用户程序不允许足够的堆栈空间。
- 第二,如果内核将数据保留在用户空间,然后从系统调用返回,那么恶意的用户可能使用这些数据找出某些关于其它进程的信息。[^1]
对于第一点,nswcfd在 内核堆栈意义?这篇帖子的2楼中说的比较明白:
- user space stack overflow直接影响kernel stack,风险太大
而对于第二点,amarant在7楼进行了说明:
- 用户对自己的sp有写的权利,如果内核使用用户栈,那么用户可以安排一个sp给kernel用。
此外:进程的堆栈 每个进程都有一个内核栈吗这两个讲的挺详细的,推荐去看。
假设用户态的堆栈过小,容易栈溢出,访问非法内存,导致系统崩溃。
在用户态,用户可以对堆栈寄存器进行操作,不安全。