运维开发网

linux-kernel – 通过mmap提供几个内核缓冲区

运维开发网 https://www.qedev.com 2020-03-19 13:51 出处:网络
我有一个内核驱动程序,它在内核空间中分配几个缓冲区(物理上连续,与页面边界对齐,并由整数页组成).
我有一个内核驱动程序,它在内核空间中分配几个缓冲区(物理上连续,与页面边界对齐,并由整数页组成).

接下来,我需要让我的驱动程序能够将一些缓冲区映射到用户空间(当然,每个mmap()调用一个缓冲区).驱动程序为此目的注册单字符设备.

用户空间程序必须能够告诉内核它想要mmap的缓冲区(例如,通过指定其索引或唯一ID,或先前通过ioctl()解析的物理地址).

我想通过使用mmap()的offset参数(例如来自用户空间)来实现:

mapped_ptr = mmap(NULL, buf_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (MAGIC + buffer_id) * PAGE_SIZE);

其中“MAGIC”是一个幻数,而buffer_id是我想要mmap的缓冲区ID.

接下来,在内核部分会有这样的东西:

static int my_dev_mmap(struct file *filp, struct vm_area_struct *vma)
{
  int bufferID = vma->vm_pgoff - MAGIC;
  /* 
   * Convert bufferID to PFN by looking through driver's buffer descriptors
   * Check length = vma->vm_end - vma->vm_start
   * Call remap_pfn_range()
   */
}

但我认为它是某种肮脏的方式,因为mmap()中的“offset”不应该指定索引或标识符,它的作用是从mmap-ed设备的开头提供跳过的字节数(或页数) (或文件)内存(应该是连续的,对吧?).

但是,我已经看到主线中的一些驱动程序使用“offset”来区分mmap-ed缓冲区.

有没有替代解决方案?

附:

我需要这一切只是因为我正在处理一些不寻常的SoC’图形控制器,它只能在物理上连续的,与8字节边界内存缓冲区对齐的情况下运行.所以,我只能在内核空间中分配这样的缓冲区,并通过mmap()将它们传递给用户空间.

控制器编程的大部分(编写指令批并将其推送到内核驱动程序)在用户空间中执行.

此外,我不能只分配单个大块的物理连续内存,因为在这种情况下它需要非常大(例如,16 MiB)并且alloc_pages_exact()将失败.

我没有看到使用offset将索引从用户空间传递给驱动程序有什么问题.如果它给你带来了麻烦,那么只需看看你的驱动程序,就是将它想要呈现给用户空间的各个页面中的大缓冲区组装成几乎连续的,这样偏移量就是这个缓冲区的偏移量.但在我看来,以这种方式做事并没有错.

另一种选择,如果你可以使用内核3.5或更新,可能是使用“连续内存分配器”(CMA) – 查看< Linux / dma-contiguous.h>和drivers / base / dma-contiguous.c了解更多信息.还有https://lwn.net/Articles/486301/作为参考,但我不知道在该文章和将代码合并到主线之间有多少(如果有的话).

0

精彩评论

暂无评论...
验证码 换一张
取 消