可以说我正在编写一个操作系统。我不是骗子,所以我从最底层开始。过了一段时间你有进程,先发制人的调度程序和Malloc。现在你需要互斥体和信号量。从头开始实施互斥锁
这是一个代码,它可以专门锁定互斥锁,或者专门增加或减少信号量。可以说我有这个代码。
然后你会得到下一步:采取互斥体。让我们说我们有两个进程,争取一个互斥体。在B可以触摸它之前,进程A是第一个并且抢占该互斥体。所以现在B必须等待。我的问题具体是关于处理等待阶段。我可以看到以下选项:
- 保持过程B上的调度和每次得到一个时间片,它会检查它是否可以锁定互斥的时间。如果没有,重新安排并等待下一个时间片。这种方法看起来非常完美,除了浪费CPU时间而无法执行任何操作。
- 介绍一个新进程,称他为Kernel。他是无所不知的人,可以接触到所有事物。如果一个进程无法锁定互斥锁,它就会进入等待状态,并且不会有更多的时间片。如果进程释放互斥量,它会通知内核,内核将在稍后获得时间片。在它的时间片中,它搜索等待互斥量的进程。等待此互斥锁的优先级最高的进程将被唤醒。
- 再次假设一个进程如果无法获得互斥量就会进入WAIT:在互斥量释放时,释放互斥量的进程必须通过进程列表并查看哪些进程正在等待互斥量。然后它唤醒最高优先级的那个。我不喜欢这个,因为我真的不想让任何进程写访问内存的任何部分。我计划使用MPU来防止这种情况,检测段错误等。如果我实现这种方法,我将更加难以正确地实现MPU部分。
这就是我所能看到的。我最喜欢2,但它仍然感觉像很多开销。我很想听听你对这个问题的意见:你如何实现等待锁定互斥锁被释放?
更多背景:我实际上是在Cortex M4 CPU上实现操作系统。我知道我将无法击败freeRTOS等。它关于学习体验。
您的第三种解决方案假定互斥体释放原语在用户空间中工作,但如果互斥体是操作系统管理对象,则释放功能是系统调用,它将触发上下文切换到内核模式,内核将实际检查等待那个互斥体的线,而不是释放过程。所以第二种情况本质上是最准确的。 – didierc 2014-11-04 10:04:13
在锁定和解锁互斥锁时,直接切换到内核的效率并不高?我只想在真正需要时切换:释放互斥锁并完成时间片之后。 – Cheiron 2014-11-04 11:23:02
@Cheiron - 这会带来非常糟糕的表现。切换到内核状态可确保等待互斥量的任何线程都已准备就绪(并且很可能正在运行),即释放互斥量的'即时'。等待一些可能的中断/系统调用使等待线程就绪/运行对于大多数情况下的性能来说将是灾难性的,特别是在具有多核的处理器上。你正在将5us的延迟变成几十毫秒。 – 2014-11-04 11:33:12