gpt4 book ai didi

c - 在用户空间和内核空间之间同步 mmap 中的队列

转载 作者:行者123 更新时间:2023-11-30 16:15:00 25 4
gpt4 key购买 nike

我有一段代码,我正在努力提高其性能。代码在概念上很简单:每 5 毫秒从内核空间的传感器获取一些数据,用这些数据填充队列,并在用户空间中读取它进行处理。

目前,我在内核空间中有一个线程填充队列,并且我有一个具有读取文件操作功能的字符设备,可以使用copy_to_user将此数据传输到用户空间。

让我向您展示代码的一个小框架:

用户空间的观点。

// In userspace side

int process_queue (void)
{
int fd = -1;
int data_offset = 0;

fd = open_char_device_from_kernel ();
while (1)
{
// read from char device data from kernel
err = read (fd, &ctx->data_queue[data_offset], SAMPLE_SIZE);
data_offset = (data_offset + SAMPLE_SIZE) % QUEUE_DATA_SIZE;

// process data
(...)
}

}

内核空间观点:

//In kernel side

static const struct file_operations fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = xxx__ioctl,
.read = xxx__read,
.open = xxx__open,
.release = xxx__release,
};

int kernel_thread(...)
{
while (1)
{
// wait signal from irq
wait_event_interruptible(wq_irq, flag_irq);
// get data and fill queue
(...)
memcpy (&queue[write_offset], rx_buf[REGISTER], SAMPLE_SIZE);
write_offset += ELEMENT_SIZE;
if (write_offset == SIZE_QUEUE) write_offset = 0;
up(&read_sem);
}
}

static int xxx_read(struct file *filp, char __user *data, size_t len, loff_t *ppos)
{
if (down_interruptible (&read_sem)) return (-EINTR);

err = copy_to_user(data, &queue[read_offset], SAMPLE_SIZE);
read_offset += ELEMENT_SIZE;
if (read_offset == SIZE_QUEUE) read_offset = 0;
return (ELEMENT_SIZE - err);
}

int probe_kernel_driver (...)
{
(...)
alloc_chrdev_region(&dev_no , 0, 1, DATA_DEVICE_NAME);
cl = class_create(THIS_MODULE, DATA_DEVICE_NAME);
device_create(cl, NULL, dev_no, NULL, DATA_DEVICE_NAME);
(...)
}

这里的主要思想是删除这段代码中的copy_to_user,这非常慢。我想使用 mmap 来代替,并且我能够在两侧实现它以共享从内核空间到用户空间的数据。仍然存在一个问题:我不知道如何同步用户空间和内核空间之间的数据。用户空间进程如何知道新数据可用?

当然,我不想使用轮询或任何其他会失去 mmap 性能增益的技术。

最佳答案

用户空间进程与内核通信的替代方案(有意)受到限制。它们包括:

  • 进行系统调用
  • 在设备上执行 I/O
  • 对内核映射文件执行 I/O,例如/proc
  • 通过信号被动接收通知

如果您愿意用户空间进程阻止数据变得可用,那么其中任何一个都是可行的可能性。如果您既不能轮询也不能阻止,那么最后一个是我看到的唯一选择。

请注意,进行系统调用或执行 I/O 并不是为了检索数据本身,而只是为了检索新数据可用的信号。

您可能需要考虑为您的设备设置一个或多个合适的 ioctl,以直接支持阻止可用数据或注册一个进程,以便在新数据到达时发出信号。

但请注意,由于大量开销,用户进程和内核之间的所有交互都相当缓慢。在这种交互过程中传输的数据量有一定的相关性,但它不是唯一的因素。这就是为什么减少程序执行的系统调用次数是一个好习惯。因此,如果基于 mmap 的方法允许您减少与内核的交互次数,则可以预期它会是一个胜利,但如果它仅改变数据传输模式,但它不会那么成功。无论何种类型,仍然需要相同数量的内核交互。 (访问 mmapped 内存本身并不是与内核的交互。)

关于c - 在用户空间和内核空间之间同步 mmap 中的队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57310711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com