调用 mmap() 时如何获取 Linux 中设备内字段的偏移量
How to get the offset of a field within a device in Linux when calling mmap()
我目前正在 Linux 设备驱动程序中实现 mmap()
。
基本上,假设已经定义了一个名为 data
的结构。我的设备的结构定义如下,
struct test_dev{
struct cdev cdev;
struct mutex lock;
struct data *data;
};
在设备的open()
方法中,data
是通过调用vmalloc()分配的。假设我想让用户调用mmap()
映射到数据字段,用户需要知道data
字段的offset
:
int fd = open("/dev/testdev", O_RDWR);
int ret = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
我在尝试找到 data
的偏移量时卡住了。
我查看了 mmap() 的联机帮助页,它说
The contents of a file mapping (as opposed to an anonymous
mapping; see MAP_ANONYMOUS below), are initialized using length
bytes starting at offset offset in the file (or other object)
referred to by the file descriptor fd.
Q1:由于data
字段是使用vmalloc()分配的,它在高端内存中,但是test_dev
结构是使用kmalloc()分配的,它在低内存中memory, addr(data) - addr(test_dev) 小于0。因此,我们不能以这种方式计算偏移量。我可以知道是否有另一种方法来获取 offset
,以便用户可以使用此 offset
到 mmap()
到 data
字段?
Q2:如果 data
字段是使用 kmalloc()
分配的,vmalloc()
方法之间会有什么区别吗?
在Linux Device Drivers中声明kmalloc()
返回的内存地址也是虚拟地址,位于低位内存。我不确定使用“addr(data) - addr(test_dev)”是否有效。以我自己的理解,不太可能行得通。
此外,由于kmalloc()
manpage说kmalloc()
是内核中为小于页面大小的对象分配内存的正常方法,因此在实现mmap()时,我们可能不会选择映射到 kmalloc()
返回的地址,因为 mmap() 映射到页面边界。
偏移量被传递给您在设备驱动程序中编写的 mmap 处理程序。你可以把它当作一个任意的 off_t
参数,这意味着你想要的任何东西。忽略它并始终 mmap data
。或者将它用作从 data
开始的偏移量,这可能是您的驱动程序最正确的语义。
驱动程序初始化时 kmalloc() 调用的结构与 mmap 无关。 offset
不是距此结构开头的偏移量。
要映射 vmalloc 内存,您需要获取每个页面,因为它们不连续,并将其添加到 vma。参见 vmalloc_to_page
和 vm_insert_page
。
我目前正在 Linux 设备驱动程序中实现 mmap()
。
基本上,假设已经定义了一个名为 data
的结构。我的设备的结构定义如下,
struct test_dev{
struct cdev cdev;
struct mutex lock;
struct data *data;
};
在设备的open()
方法中,data
是通过调用vmalloc()分配的。假设我想让用户调用mmap()
映射到数据字段,用户需要知道data
字段的offset
:
int fd = open("/dev/testdev", O_RDWR);
int ret = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
我在尝试找到 data
的偏移量时卡住了。
我查看了 mmap() 的联机帮助页,它说
The contents of a file mapping (as opposed to an anonymous mapping; see MAP_ANONYMOUS below), are initialized using length bytes starting at offset offset in the file (or other object) referred to by the file descriptor fd.
Q1:由于data
字段是使用vmalloc()分配的,它在高端内存中,但是test_dev
结构是使用kmalloc()分配的,它在低内存中memory, addr(data) - addr(test_dev) 小于0。因此,我们不能以这种方式计算偏移量。我可以知道是否有另一种方法来获取 offset
,以便用户可以使用此 offset
到 mmap()
到 data
字段?
Q2:如果 data
字段是使用 kmalloc()
分配的,vmalloc()
方法之间会有什么区别吗?
在Linux Device Drivers中声明kmalloc()
返回的内存地址也是虚拟地址,位于低位内存。我不确定使用“addr(data) - addr(test_dev)”是否有效。以我自己的理解,不太可能行得通。
此外,由于kmalloc()
manpage说kmalloc()
是内核中为小于页面大小的对象分配内存的正常方法,因此在实现mmap()时,我们可能不会选择映射到 kmalloc()
返回的地址,因为 mmap() 映射到页面边界。
偏移量被传递给您在设备驱动程序中编写的 mmap 处理程序。你可以把它当作一个任意的 off_t
参数,这意味着你想要的任何东西。忽略它并始终 mmap data
。或者将它用作从 data
开始的偏移量,这可能是您的驱动程序最正确的语义。
驱动程序初始化时 kmalloc() 调用的结构与 mmap 无关。 offset
不是距此结构开头的偏移量。
要映射 vmalloc 内存,您需要获取每个页面,因为它们不连续,并将其添加到 vma。参见 vmalloc_to_page
和 vm_insert_page
。