linux kernel 等待队列

Linux内核中的“等待队列”是一种数据结构,用于管理正在等待某种条件变为真的线程。它们是线程在内核空间中阻塞(或“睡眠”)的正常方法。多年来,等待队列机制已经发展成为一个相当复杂和复杂的内核子系统。但是,现在可以使用为实时树开发的等待队列变体来简化该代码。结果可能是内核中大量的代码搅动。

看一下<linux/wait.h> from the 2.0 kernel揭示了一个简单的数据结构:等待线程的基本链接列表。等待队列上的wake_up()调用将遍历列表,从而使每个线程进入可运行状态。没有比这更多的东西了。然后,在1999年,臭名昭著的Mindcraft研究指出了Linux的一些性能缺陷。其中之一是“雷声成群”问题,其中多个过程将被唤醒并争夺一种资源,而只有其中一个可以获得。结果,添加了“排他的等待”功能-只有可能在许多等待线程中的第一个唤醒。然后在2.5系列中添加了回调机制,以便在其他情况下可以阻塞时,新的异步I / O工具可以介入。等等。

最终结果是,数据结构比2.0天的数据结构更大,更复杂。但是,对于实时树而言,最有问题的是回调功能。由于这些回调可以进入睡眠状态,因此它们阻止使用“原始”自旋锁来保护等待队列本身。为解决此问题,Thomas Gleixner创建了一种新的“简单等待队列”机制,该机制将免除大多数添加的功能,因此适合在实时内核中使用。

2013年Realtime Linux Workshop将这一代码确定为相对容易进入主线的候选对象。作为回应,Paul Gortmaker提取了简单的等待队列工具,并将发布的补丁系列发布以供审查。

该代码看起来很像回到2.0内核。在此期间,等待队列获得的许多功能已被剥夺,留下了看上去很熟悉的等待线程链接列表。没有独占的唤醒功能,没有回调功能,并且没有太多其他功能。但是,有一种等待队列机制,足以满足内核中大多数等待队列用户(其中​​有很多)的需求。

该API与现有的等待队列相似。等待队列条目和等待队列头定义为:

   #include <linux/swait.h>

    DEFINE_SWAITER(name);
    DEFINE_SWAIT_HEAD(name);

需要直接调用schedule()以使调用线程进入睡眠状态的低级API如下所示:

   void swait_prepare(struct swait_queue_head *head, struct swaiter *w, int state);
    void swait_finish(struct swait_queue_head *head, struct swaiter *w);

swait_prepare()调用用于将进程添加到给定的等待队列头,并将其置于适当的睡眠状态。在执行了所有必要的检查并调用了schedule()之后,新唤醒的线程将调用swait_finish()将其从队列中删除并进行清理。

当前的等待队列实现具有大量宏,以简化等待条件的任务。对于简单的等待队列,有一个类似的集合,但是要小得多:

    wait_event_cmd(wq, condition, cmd1, cmd2);
    wait_event_hrtimeout(wq, condition, timeout);
    wait_event_killable(wq, condition);
    wait_event_lock_irq_cmd(wq, condition, lock, cmd);
    wait_event_lock_irq(wq, condition, lock);
    wait_event_interruptible_hrtimeout(wq, condition, timeout);
    wait_event_interruptible_exclusive(wq, condition);
    wait_event_interruptible_locked(wq, condition);
    wait_event_interruptible_locked_irq(wq, condition);
    wait_event_interruptible_exclusive_locked(wq, condition);
    wait_event_interruptible_exclusive_locked_irq(wq, condition);
    wait_event_interruptible_lock_irq_cmd(wq, condition, lock, cmd);
    wait_event_interruptible_lock_irq(wq, condition, lock);
    wait_event_interruptible_lock_irq_timeout(wq, condition, lock, timeout);

如果需要,添加上述大多数宏的“简单”版本几乎没有什么障碍;有趣的是,未来几年将有多少人出现。不用说,也没有什么像过时的sleep_on()接口。可以肯定地说,没有人会尝试添加该版本。
Paul的帖子指出,即使仅在几个地方使用它们,添加简单的等待队列也会使内核更小。考虑到接口的尺寸减小和相对简单,毫无疑问,到目前为止,没有人反对添加此代码。唯一真正的问题是如何进行添加。
Christoph Hellwig建议,简单的等待队列可以简单地替换当前的实现,只需更改一些稀奇古怪的功能以使用新名称使用旧代码即可。保罗担心这种大范围的改变会造成一个卖旗日,而问题与以奇怪的方式与等待队列的改变有关。
没有人想要这种情况,因此简单的等待队列似乎更有可能保留其“等待”命名方案。内核可能会看到现有等待队列的整体命名更改,以明确表明现在可以进行选择了。因此,我们可能会看到一个很大的补丁,将wait_event()更改为cwait_event(),依此类推,而没有更改功能。之后,可以将各个呼叫站点随意更改为简单的等待队列。结果将是相当数量的代码搅动,但是这种搅动应该留下一个更小,更简单的内核。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值