Reputation: 415
I am currently implementing mmap()
in a Linux device driver.
Basically, suppose there is a struct called data
that is already defined. My device's struct is defined as follows,
struct test_dev{
struct cdev cdev;
struct mutex lock;
struct data *data;
};
In device's open()
method, data
is allocated by calling vmalloc(). Suppose I would like to let user call mmap()
to map to the data field, the user needs to know the offset
of data
field:
int fd = open("/dev/testdev", O_RDWR);
int ret = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
I got stuck when trying to find the offset of data
.
I looked into the manpage of mmap(), it says
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: Since data
field is allocated using vmalloc(), it is in high memory, but test_dev
structure is allocated using kmalloc(), which is in low memory, addr(data) - addr(test_dev) is less than 0. Therefore, we cannot compute the offset in such way. May I know if there is another approach to get the offset
, so that the user could use this offset
to mmap()
to the data
field?
Q2: If instead the data
field is allocated using kmalloc()
, will there be any difference between the vmalloc()
approach?
In Linux Device Drivers, it states that memory addresses returned by kmalloc()
is also virtual address, and it is located in low memory. I am not sure if using "addr(data) - addr(test_dev)" would work. Based on my own understanding, it is unlikely to work.
Besides, since kmalloc()
manpage says kmalloc()
is the normal method of allocating memory for objects smaller than page size in the kernel, when implementing mmap(), we may not choose to map to the address returned by kmalloc()
since mmap() maps on a page boundary.
Upvotes: 1
Views: 651
Reputation: 4682
The offset is passed to the mmap handler you write in your device driver. You can treat it as an arbitrary off_t
parameter that means anything you want. Just ignore it and always mmap data
. Or use it as an offset from the start of data
, which is probably the most correct semantics for your driver.
The struct you kmalloc()'ed when your driver initialized has nothing to do with mmap. offset
is not an offset from the start of this struct.
To mmap vmalloc memory, you need to get each page, since they are not contiguous, and add it to the vma. See vmalloc_to_page
and vm_insert_page
.
Upvotes: 3