了解Linux内核循环缓冲区

有一篇文章在http://lwn.net/Articles/378262/上描述了Linux内核的循环缓冲区实现。 我有一些疑问:

这里是“制片人”:

spin_lock(&producer_lock); unsigned long head = buffer->head; unsigned long tail = ACCESS_ONCE(buffer->tail); if (CIRC_SPACE(head, tail, buffer->size) >= 1) { /* insert one item into the buffer */ struct item *item = buffer[head]; produce_item(item); smp_wmb(); /* commit the item before incrementing the head */ buffer->head = (head + 1) & (buffer->size - 1); /* wake_up() will make sure that the head is committed before * waking anyone up */ wake_up(consumer); } spin_unlock(&producer_lock); 

问题:

  1. 由于这段代码明确地处理内存顺序和primefaces性spin_lock()是什么点?
  2. 到目前为止,我的理解是,ACCESS_ONCE停止编译器重新sorting,是真的?
  3. 是否produce_item(item)只是发出与该项目相关的所有写入?
  4. 我相信smp_wmb()保证在produce_item(item)中的所有写入在它之后的“发布”写入之前完成。 真正?
  5. 我得到这个代码的页面上的注释似乎意味着更新头索引后通常需要smp_wmb(),但wake_up(消费者)这样做,所以它不是必要的。 真的吗? 如果是这样的话

这里是“消费者”:

 spin_lock(&consumer_lock); unsigned long head = ACCESS_ONCE(buffer->head); unsigned long tail = buffer->tail; if (CIRC_CNT(head, tail, buffer->size) >= 1) { /* read index before reading contents at that index */ smp_read_barrier_depends(); /* extract one item from the buffer */ struct item *item = buffer[tail]; consume_item(item); smp_mb(); /* finish reading descriptor before incrementing tail */ buffer->tail = (tail + 1) & (buffer->size - 1); } spin_unlock(&consumer_lock); 

针对“消费者”的问题:

  1. smp_read_barrier_depends()是做什么的? 从一个论坛上的一些评论看来,你可能已经在这里发布了一个smp_rmb(),但是在一些体系结构中,这是不必要的(x86),并且太昂贵了,所以smp_read_barrier_depends()被创build来做这个select。也就是说,真的不明白为什么smp_rmb()是必要的!
  2. smp_mb()在那里保证所有的读之前写完之后呢?

对于生产者:

  1. 这里的spin_lock()是为了防止两个生产者试图同时修改队列。
  2. ACCESS_ONCE可以防止重新排序,也可以防止编译器稍后重新加载值。 ( 有关LWN上的ACCESS_ONCE的一篇文章 ,进一步扩展了这一点)
  3. 正确。
  4. 也是正确的。
  5. 消费者在唤醒消费者之前需要(隐含的)写屏障,否则消费者可能看不到更新的head值。

消费者:

  1. smp_read_barrier_depends()是一个数据依赖障碍,它是一个读取障碍的较弱形式(见2 )。 在这种情况下的效果是确保在将buffer->tail用作buffer[tail]的数组索引之前将其读取。
  2. smp_mb()在这里是一个完整的内存屏障,确保所有的读写都是由这一点提交的。

其他参考:

  • 关于内存障碍的Linux内核文档

(注:我并不完全确定我在制作人和消费者中的5个答案,但我相信他们是事实的一个公平的近似值,我强烈推荐阅读关于记忆障碍的文档页面,因为它更多比我能写的任何东西都要全面。)