c - 使用 Linux 内核中的循环缓冲区宏

标签 c linux-kernel

我有一个关于在 Linux 内核中使用循环缓冲区宏的问题。

我正在尝试使用 include/linux/circ_buf.h 中的循环缓冲区宏。

ACCESS_ONCE() 宏用于确保编译器从内存中读取值,而不是尝试优化访问。

在循环缓冲区的文档中,给出了以下代码作为生产者的示例:

        spin_lock(&producer_lock);

        unsigned long head = buffer->head;
        /* The spin_unlock() and next spin_lock() provide needed ordering. */
        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_store_release(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);

我有 3 个问题:

  1. 我不确定的是,在读取 buffer->tail 的值时是否需要使用 ACCESS_ONCE,因为在我的函数中我只需要读取 buffer->tail 一次。我在函数开始时读取该值,然后在整个函数中使用该值。 我假设编写此示例代码的想法是它在循环中运行,并且必须在每次迭代中从内存中读取新的尾部值。

  2. 我认为如果你有一个生产者和一个消费者,你就不需要使用自旋锁。 这里为什么使用自旋锁?

  3. 这里还有这样的评论:

    /*wake_up()将确保头部在之前被提交 * 叫醒任何人 */

    如果我在代码中不使用wake_up,是否需要使用内存屏障? smp_store_release()不是已经发出了内存屏障吗?

最佳答案

  1. 如果没有ACCESS_ONCE,编译器将可以优化代码,以便多次读取变量。

  2. 当生产者和消费者可以并发运行以及共享变量必须以原子方式更新时,您需要自旋锁。

  3. 无论使用什么机制来唤醒消费者,都必须确保之前的写入和唤醒是有序的。

关于c - 使用 Linux 内核中的循环缓冲区宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26656071/

相关文章:

linux - 关于结构 "i_count"的成员 "inode"

c++ - 在 C++ 中的 Windows 上使用 SendInput 发送同步键盘事件

c - 为什么主函数中b的值没有改变?

c - 使用 malloc() 函数设置全局数组大小获取转储核心

linux - Linux 内核中的 netlink 套接字与来自用户空间的轮询有何不同?

linux-kernel - Linux 设备树,具有多个中断父节点的节点

c - struct 的成员正在被修改,但为什么呢?

c - Doxygen 的页面跨多个评论 block

linux - 从内核中断读取设备

Linux 内核线程问题