【问题标题】:Threads in userspace and yield用户空间中的线程和产量
【发布时间】:2011-04-16 11:05:35
【问题描述】:

我应该在 C 中实现一个用户级线程库。为此,我需要实现 yield()createThread()destroyThread() 函数。我相信我已经掌握了基本知识:

为了跟踪线程,我将使用如下所示的ThreadControlBlock 元素队列(类似于操作系统中的PCBs):

struct ThreadControlBlock { 
    int ThreadId, 
    u_context *context };

我们可以使用setcontext() 系列函数来“保存”和“加载”上下文。 程序初始化后,初始化没有元素的 ThreadQueue。

现在我没有得到的部分:当一个线程调用yield() 时,我获取当前上下文并将其保存在ThreadControlBlock 中并放入队列中。然后获取队列中的第一个元素并在其中加载上下文,然后继续执行。

问题是,如果我这样做,假设我是一个调用yield() 的线程,而下一个线程是我自己。如果我保存上下文并再次加载它,在重新输入时,我会不会在我所在的位置(在调用 yield() 之前?)这会一直持续下去吗?

【问题讨论】:

  • +1 用于与家庭作业相关的示例性问题,而不仅仅是“请为我做作业”。这本身就是一个有趣的问题,它触及了任务上下文切换如何实际工作的核心。

标签: c multithreading operating-system


【解决方案1】:

在您的 yield() 实现中检查下一个线程是否是当前线程并将这种情况视为无操作是完全合理的。

【讨论】:

  • @pessimopoppotamus:如果没有其他线程,那么您必须这样做。来自任务调度程序的有趣示例:它们都不支持 0 个任务。这就是为什么 Windows 有“系统空闲任务”而 *NIX 有“init”的原因。所以调度程序总是有一些事情要安排。 yield() 作为调度程序的调用,本质上是允许cooperative multi-tasking 的一种方式。如果没有人可以“合作”,yield() 什么也做不了。
【解决方案2】:

当线程调用yield() 时,您必须保存即将从yield() 调用返回的线程的状态。不要保存 yield() 之前的上下文。

【讨论】:

    【解决方案3】:

    如果除了当前线程之外没有其他线程可以运行,那么除了从yield返回之外就没有其他事情可做。不过,在这种情况下,我不会打扰调用 swapcontext —— 只需检测并返回。

    我认为您实际处理的是在调用 yield 时没有线程(包括当前线程)时要做什么。处理这个问题的一个简单方法是有一个空闲线程,它只在运行队列(就绪线程)为空时运行。这个线程可能只是:

       {
           while (1) {
               yield();
               pause();
           }
       }
    

    这允许您的程序进入睡眠状态(通过暂停),直到信号发生。希望信号是某个事件,使其他线程之一准备好运行,因此下一次对 yield 的调用将运行另一个线程,而不是再次运行空闲线程。

    【讨论】:

      【解决方案4】:

      如果您要切换到另一个任务,同样的问题实际上也适用 - 因为另一个任务在同一点(即将切换到第二个任务的位置)保存了它的上下文。使用setcontext()getcontext(),您需要使用静态变量来跟踪您是在切换还是切换:

      static volatile int switched;
      
      switched = 0;
      getcontext(current->context);
      if (!switched)
      {
         switched = 1;
         setcontext(next->context);
      }
      

      或者,您可以只使用swapcontext(current->context, next->context);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-16
        • 1970-01-01
        • 2017-04-20
        • 1970-01-01
        • 1970-01-01
        • 2012-04-30
        • 1970-01-01
        • 2012-01-17
        相关资源
        最近更新 更多