2014-11-04 59 views
1

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

这是一个代码,它可以专门锁定互斥锁,或者专门增加或减少信号量。可以说我有这个代码。

然后你会得到下一步:采取互斥体。让我们说我们有两个进程,争取一个互斥体。在B可以触摸它之前,进程A是第一个并且抢占该互斥体。所以现在B必须等待。我的问题具体是关于处理等待阶段。我可以看到以下选项:

  1. 保持过程B上的调度和每次得到一个时间片,它会检查它是否可以锁定互斥的时间。如果没有,重新安排并等待下一个时间片。这种方法看起来非常完美,除了浪费CPU时间而无法执行任何操作。
  2. 介绍一个新进程,称他为Kernel。他是无所不知的人,可以接触到所有事物。如果一个进程无法锁定互斥锁,它就会进入等待状态,并且不会有更多的时间片。如果进程释放互斥量,它会通知内核,内核将在稍后获得时间片。在它的时间片中,它搜索等待互斥量的进程。等待此互斥锁的优先级最高的进程将被唤醒。
  3. 再次假设一个进程如果无法获得互斥量就会进入WAIT:在互斥量释放时,释放互斥量的进程必须通过进程列表并查看哪些进程正在等待互斥量。然后它唤醒最高优先级的那个。我不喜欢这个,因为我真的不想让任何进程写访问内存的任何部分。我计划使用MPU来防止这种情况,检测段错误等。如果我实现这种方法,我将更加难以正确地实现MPU部分。

这就是我所能看到的。我最喜欢2,但它仍然感觉像很多开销。我很想听听你对这个问题的意见:你如何实现等待锁定互斥锁被释放?

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

+1

您的第三种解决方案假定互斥体释放原语在用户空间中工作,但如果互斥体是操作系统管理对象,则释放功能是系统调用,它将触发上下文切换到内核模式,内核将实际检查等待那个互斥体的线,而不是释放过程。所以第二种情况本质上是最准确的。 – didierc 2014-11-04 10:04:13

+0

在锁定和解锁互斥锁时,直接切换到内核的效率并不高?我只想在真正需要时切换:释放互斥锁并完成时间片之后。 – Cheiron 2014-11-04 11:23:02

+0

@Cheiron - 这会带来非常糟糕的表现。切换到内核状态可确保等待互斥量的任何线程都已准备就绪(并且很可能正在运行),即释放互斥量的'即时'。等待一些可能的中断/系统调用使等待线程就绪/运行对于大多数情况下的性能来说将是灾难性的,特别是在具有多核的处理器上。你正在将5us的延迟变成几十毫秒。 – 2014-11-04 11:33:12

回答

2

通常,这是发生了什么:

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

线程B尝试通过使系统调用引用它来获取互斥锁。互斥体被采用,所以B被从正在运行的线程列表中取出并插入到互斥体结构中的队列中。内核返回到准备好的其他线程。线程B现在是死代码和堆栈。

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

不需要'内核进程',只需要内核代码和数据。

不需要'时间片'。 Timeslices与此功能无关。

'搜索进程等待互斥'是一个队列弹出,O(1)。评论后

编辑:

“这意味着每一个进程可以访问相关 调度所有记忆”

不是所有的时间,因为系统调用更改为内核状态然后回来。用户状态的线程不需要对内核内存进行无限制的访问。

你需要互斥体或信号灯开始等待互斥或 信号量(以保证队列的线程安全)。

不。通常情况下,移动容器之间的线程意味着删除并只插入一个指向线程控制块的指针。这样的操作非常快,偶尔的争用可以通过原子自旋锁,中断禁用或更复杂的涉及内核通信驱动程序的序列化/保护机制来避免。

+1

几乎可以肯定你的意思是_Thread A释放互斥锁...... _ – Arno 2014-11-04 11:44:16

+0

这个解决方案有一些问题,虽然它看起来非常非常好。所以,在拍摄之前:荣誉。问题在于:第一:这意味着每个进程都可以访问与调度程序相关的所有内存(如现有进程的列表),而B:您需要互斥或信号才能开始等待互斥或信号量(以确保线程安全与该互斥体相关的队列)。第二个困扰我的是因为你继续产生互斥体/信号量以确保你能够等待所说的互斥体/信号量。 – Cheiron 2014-11-04 13:55:09

+0

@Arno确实。更糟糕的是,如果你看编辑历史,它首先会说'线程A',但后来我认为它是错误的,所以我将它改为'B'。基本上,我搞砸了两次:) – 2014-11-04 15:03:38