我正在研发专有设备驱动程序。驱动程序实现为内核模块。然后,该模块与用户空间进程相结合。
每次设备生成中断时,驱动程序必须直接在中断处理程序的上半部分内更新用户空间进程的地址空间中的一组计数器。驱动程序知道用户进程的PID和task_struct,并且还知道计数器位于用户进程上下文中的虚拟地址。但是,我无法弄清楚在中断上下文中运行的代码如何占用用户进程的mm上下文并写入它。让我总结一下我需要做的事情:
获取与用户进程上下文中计数器的虚拟地址对应的物理页面和偏移的地址。
在页面表中设置映射并写入与计数器对应的物理页面。
为此,我尝试了以下方法:
尝试接受用户任务的mm上下文,如下所示:
use_mm(tsk->mm);
/* write to counters. */
unuse_mm(tsk->mm);
这显然会导致整个系统挂起。
当我们的用户进程是时,等待中断发生
current
进程。然后使用copy_to_user()
。
我不是内核编程方面的专家。如果这是一个很好的方法,请提前建议并提前感谢。
答案 0 :(得分:3)
您的驱动程序应该是映射内核的内存用于用户空间进程的驱动程序。例如,您可以为您的设备实施.mmap
的{{1}}回调。
内核驱动程序可以随时写入已映射的内核地址(即使在中断处理程序中)。用户空间进程将立即看到映射一侧的所有修改(使用通过struct file_operation
系统调用获得的地址)。
答案 1 :(得分:2)
Unix的架构对访问用户空间的中断例程不以为然 因为在中断发生时(理论上)可以交换进程。 如果进程在另一个CPU上运行,那也可能是个问题。 我建议你写一个ioctl来同步计数器, 然后让进程调用ioctl 每次需要访问计数器时。
答案 2 :(得分:2)
在中断上下文之外,您的驱动程序需要检查用户内存是否可访问(使用access_ok
),并使用get_user_pages
或get_user_pages_fast
固定用户内存(确定后)要固定的区域的起点的页面偏移量,以及要固定的区域跨越的页面数,包括两端的页面对齐。它还需要使用vmap
将页面列表映射到内核地址空间。来自vmap
的返回地址加上其页面中区域开头的偏移量,将为您提供中断处理程序可以访问的地址。
在某些时候,您将希望终止对用户内存的访问,这将涉及确保您的中断例程不再访问它,调用vunmap
(传递vmap
返回的指针)以及put_page
或get_user_pages
固定的每个网页的get_user_pages_fast
调用序列。
答案 3 :(得分:1)
我不认为你想做的事情是可能的。考虑这种情况: (假设您的设备如何工作)
某些函数为计数器分配用户空间内存 在PROCESS X中提供其地址。
发生切换并执行PROCESS Y.
您的计数器地址无法访问。
您需要安排在PROCESS X执行时执行的内核模式异步事件(下半部分)。