对于lab4 (课堂练习中的代码, related_info/lab4)的进程调度, 估计关中断没什么作用, 因为这里面的调度都是主动调度(通过的调用schedule来实现), 没有牵扯到时钟里面的调度, 所以哪怕不关中断, 程序也能正常运行.
但是对于关中断的机制代码中连续多次关中断是有专门的意图还是误写?如下:
在schedule中, 有一次关中断:
```
local_intr_save(intr_flag);
```
然后, 准备运行下一个就绪进程时, 调用proc_run, 如下:
```
if (next != current) {
proc_run(next);
}
```
其实在proc_run中又有local_intr_save(intr_flag);操作, 这不是相当于多次进行同一个操作了?虽然没问题, 但我实在想不出其必要性!!
另外, 对于前面关中断有个小困扰的地方, 在这里说说我的理解:
前面每次在调用进程切换schedule的时候;都会关中断, 然后切换到下一个进程的地方, 其实对于每次关中断都是主动的进程来说, 这是没有问题的, 或者简单来说, 上个进程的关中断可由下一个进程的开中断来平衡, 所以总的来说, 中断的处理是平衡的.
但是对于新建的进程来说, 所有环境本应该都是和父进程一模一样, 但是ucore中为了简化, 将子进程的函数栈帧做了更改, 如下:
```
copy_thread(struct proc_struct *proc, uintptr_t esp, struct trapframe *tf) {
proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - 1;
*(proc->tf) = *tf;
proc->tf->tf_regs.reg_eax = 0;
proc->tf->tf_esp = esp;
proc->tf->tf_eflags |= FL_IF;
proc->context.eip = (uintptr_t)forkret;
proc->context.esp = (uintptr_t)(proc->tf);
}
```
对于函数的返回地址和堆栈都修改了, 当时还奇怪为什么只有两2个page来做父子进程的栈, 其实根本就没有拷贝父进程的堆栈, 在kernel_thread_entry处的处理如下:
```
kernel_thread_entry: # void kernel_thread(void)
pushl %edx # push arg
call *%ebx # call fn
pushl %eax # save the return value of fn(arg)
call do_exit # call do_exit to terminate current thread
```
也就是说, 只要执行完函数后就会退出, 所以完全不管父进程的中断的情况, 但是在初始化栈帧的时候, 强制的将中断打开, 如: proc->tf->tf_eflags |= FL_IF;
这个在外界没有关中断的情况下是没有问题的, 但是如果出现这种情况: 在关中断的情况下, 创建出一个进程, 并主动切换到该进程, 就相当于开了一次中断.(总感觉有问题, 但想不出什么好的例子来证明!!)