我试图直接从内核模块写入它创建的进程,而不需要副本。请注意,我不能像通常那样简单地在内核模式下分配内存并将其映射到用户态,我需要内存最终源自进程本身(最终来自对 CUDA 运行时的调用)。
现在我有一个带有写入回调的 proc 文件设置,我用它从用户区发送缓冲区:
char *buffer;
const size_t PAGE_SIZE = getpagesize();
posix_memalign(&buffer,PAGE_SIZE,PAGE_SIZE);
*buffer = 89;
FILE *fp = fopen("/proc/dt/alloc", "w");
fwrite(buffer, 1, 100, fp);
在内核模块中,我将页面映射到内核内存并修改第一个字节,如下所示:
static ssize_t write_proc_alloc(struct file *file, const char __user *ubuf, size_t count, loff_t *data)
{
struct page *pages[1];
mmap_read_lock(current->mm);
pin_user_pages((unsigned long)ubuf,1, FOLL_WRITE, pages);
char *buf = kmap(pages[0]);
*buf = 123;
kunmap(pages[0]);
set_page_dirty(pages[0]);
unpin_user_pages(pages, 1);
mmap_read_unlock(current->mm);
}
我已确保将页面设置为脏,但在
fwrite
返回后它仍然保持不变。为什么我的修改不可见,如何直接修改提供的缓冲区而不需要求助于copy_to_user
之类的东西?
感谢 Ian Abbott 带领我走上正确的道路。
解决方案是使用一定程度的间接寻址,因为传递给内核函数的指针
write_proc_alloc
与用户提供的指针不同。相反,您编写一个指针,使用 get_user(ptr,(uintptr_t*)ubuf)
按值复制该指针,然后从那里映射内存并像以前一样写入。