从头开始实现互斥

时间:2014-11-04 09:58:36

标签: multithreading mutex implementation

让我们说我正在写一个操作系统。我不是骗子,所以我从最底层开始。过了一段时间,你就有了进程,一个先发制人的调度程序和Malloc。现在你需要互斥锁和信号量。

这个代码可以专门锁定互斥锁,也可以专门增加或减少信号量。假设我有这段代码。

然后你进入下一步:使用互斥锁。让我们说我们有两个进程,争夺一个互斥量。进程A是第一个并且在B可以触摸它之前抢夺互斥锁。所以现在B必须等待。我的问题是关于处理等待阶段。我可以看到以下选项:

  1. 将进程B保留在调度程序上,每次获得时间片时,它都会检查它是否可以锁定互斥锁。如果没有,请重新安排并等待下一个时间片。这种方法看起来非常完美,除了在不能做任何事情的进程上浪费CPU时间。
  2. 介绍一个新进程,称他为Kernel。他是无所不知的人,可以访问一切。如果一个进程无法锁定互斥锁,它将进入等待状态,并且不会再获取更多的时间片。如果进程释放互斥锁,它会通知内核,内核稍后会得到一个时间片。在其时间片中,它搜索等待互斥锁的进程。等待此互斥锁的具有最高优先级的进程将被唤醒。
  3. 同样,假设一个进程在无法获取互斥锁的情况下进入WAIT:在互斥发布时,释放互斥锁的进程必须通过进程列表并查看等待互斥锁的进程。然后它唤醒具有最高优先级的那个。我不喜欢这个,因为我真的不想给任何进程写入访问内存的任何部分。我打算使用MPU来防止这种情况,检测段错误等。如果我实现这种方法,我将更难以正确实现MPU部件。
  4. 这就是我能看到的。我最喜欢2,但它仍然感觉很多开销。我很想听听你对这个问题的看法:你如何实现等待锁定的互斥锁被释放?

    更多背景知识:我实际上是在Cortex M4 CPU上实现操作系统。我知道我无法击败freeRTOS等关于学习经历。

1 个答案:

答案 0 :(得分:2)

通常情况如下:

线程A尝试通过创建引用它的系统调用来获取互斥锁。没有其他线程具有互斥锁,因此其调用成功。 A运行..

线程B尝试通过创建引用它的系统调用来获取互斥锁。获取互斥锁,因此将B从正在运行的线程列表中取出并插入到互斥结构中的队列中。内核返回到另一个已准备好的线程。线程B现在是死代码和堆栈。

线程A通过创建引用它的系统调用来释放互斥锁。检查互斥锁线程队列是否有条目,并且它具有。线程B从队列中弹出并添加到就绪线程列表中。调度程序/调度程序决定在核心上运行哪一组就绪线程。线程B可以在该集合中,这取决于他的调度算法和所有其他线程上存储的状态数据。线程B可以在线程A之外的另一个核心上运行,它可以立即抢占线程A(从运行到准备就绪),或者它可能根本不运行,因为可用的核心用于运行其他更高级别的线程

没有'内核进程'是必需的,只是内核代码和数据。

没有' timeslices'是必需的还是需要的。 Timeslices与此功能无关。

&#39>搜索等待互斥锁的进程'是一个队列弹出,O(1)。

评论后编辑:

  

'这意味着每个进程都可以访问与之相关的所有内存   调度'

并非所有时间,因为系统调用会更改为内核状态,然后返回。用户状态中的线程不需要对内核内存具有不受限制的访问权限。

  

您需要互斥锁或信号量才能开始等待互斥锁或   信号量,(以确保队列的线程安全)。

没有。通常,在容器之间移动线程意味着仅移除和插入指向线程控制块的指针。这样的操作非常快,并且可以通过原子自旋锁,中断禁用或涉及核间通信驱动程序的更复杂的序列化/保护机制来避免非常偶然的争用。