MIT 6.S081操作系统之 多进程和多线程

相关知识

使用锁的例子(内存页空闲链表)

假设两个CPU同时要释放内存。假设CPU0先运行,那么CPU0会将它的变量r的next指向当前的freelist。如果CPU1在同一时间运行,它会将自己的变量r的next也指向当前的freelist。现在两个物理page对应的变量r都指向了同一个freelist(注,也就是原来单链表的head节点)。

因为我们这里只有一个内存,所以总是有一个CPU会先执行,另一个后执行。我们假设CPU0先执行,那么freelist(空闲内存页链表头)会等于CPU0的变量r。之后CPU1再执行,它又会将freelist更新为CPU1的变量r。这样的结果是,在之后的内存管理中,我们只知道CPU1的设置的变量r。我们丢失了CPU0对应的page。CPU0想要释放的内存page最终没有出现在freelist数据中。事实中,我们可能有更多的cpu,会发生更多奇怪的现象。

线程

xv6中一个进程只有一个线程,linux中一个进程可有多个线程

线程状态:

  • RUNNING,线程当前正在某个CPU上运行

  • RUNABLE,线程还没有在某个CPU上运行,但是一旦有空闲的CPU就可以运行

  • SLEEPING,这个状态意味着线程在等待一些I/O事件,它只会在I/O事件发生了之后运行

定时器中断。在每个CPU核上,都存在一个硬件设备,它会定时产生中断。定时器中断处理程序,将CPU出让(yield)给线程调度器。将一个RUNNING线程转换成一个RUNABLE线程

线程切换

当用户程序在运行时,实际上是用户进程中的一个用户线程在运行。如果程序执行了一个系统调用或者因为响应中断走到了内核中,那么相应的用户空间状态会被保存,同时属于这个用户程序的内核线程被激活。

在XV6中,任何时候都需要经历:

  • 1.从一个用户进程切换到另一个用户进程,都需要从第一个用户进程接入到内核中,保存用户进程的状态并运行第一个用户进程的内核线程。

    扫描二维码关注公众号,回复: 15783221 查看本文章
  • 2.再从第一个用户进程的内核线程切换到第二个用户进程的内核线程。

  • 3.之后,第二个用户进程的内核线程暂停自己,并恢复第二个用户进程的用户寄存器。

  • 4.最后返回到第二个用户进程继续执行。

注意

每一个CPU核在一个时间只会做一件事情,每个CPU核在一个时间只会运行一个线程,它要么是运行用户进程的线程,要么是运行内核线程,要么是运行这个CPU核对应的调度器线程。所以在任何一个时间点,CPU核并没有做多件事情,而是只做一件事情。线程的切换创造了多个线程同时运行在一个CPU上的假象。类似的每一个线程要么是只运行在一个CPU核上,要么它的状态被保存在context中。线程永远不会运行在多个CPU核上,线程要么运行在一个CPU核上,要么就没有运行。

猜你喜欢

转载自blog.csdn.net/qq_52353238/article/details/129439891