Search code examples
linux-kernellockingmmapproducer-consumercritical-section

shared lock-free queue between kernel/user address space


I am trying to construct two shared queues(one command queue, and one reply queue) between user and kernel space. So that kernel can send message to userspace and userspace can send reply to kernel after it finishes the processing.

What I have done is use allocate kernel memory pages(for the queues) and mmap to user space, and now both user and kernel side can access those pages(here I mean what is written in kernel space can be correctly read in user space, or vise versa).

The problem is I don't know how I can synchronize the access between kernel and user space. Say if I am going to construct a ring buffer for multi-producer 1-consumer scheme, How to those ring buffer access don't get corrupted by simultaneous writes?

I did some research this week and here are some possible approaches but I am quite new in kernel module development and not so sure whether it will work or not. While digging into them, I will be so glad if I can get any comments or suggestions:

  1. use shared semaphore between user/kernel space: Shared semaphore between user and kernel spaces

    But many system calls like sem_timedwait() will be used, I am worrying about how efficient it will be.

  2. What I really prefer is a lock-free scheme, as described in https://lwn.net/Articles/400702/. Related files in kernel tree are:

    • kernel/trace/ring_buffer_benchmark.c
    • kernel/trace/ring_buffer.c
    • Documentation/trace/ring-buffer-design.txt

    how lock-free is achieved is documented here: https://lwn.net/Articles/340400/

    However, I assume these are kernel implementation and cannot directly be used in user space(As the example in ring_buffer_benchmark.c). Is there any way I can reuse those scheme in user space? Also hope I can find more examples.

  3. Also in that article(lwn 40072), one alternative approach is mentioned using perf tools, which seems similar what I am trying to do. If 2 won't work i will try this approach.

    The user-space perf tool therefore interacts with the kernel through reads and writes in a shared memory region without using system calls.

Sorry for the English grammar...Hope it make sense.


Solution

  • For syncrhonize between kernel and user space you may use curcular buffer mechanism (documentation at Documentation/circular-buffers.txt).

    Key factor of such buffers is two pointers (head and tail), which can be updated separately, which fits well for separated user and kernel codes. Also, implementation of circular buffer is quite simple, so it is not difficult to implement it in user space.

    Note, that for multiple producers in the kernel you need to syncrhonize them with spinlock or similar.