考虑一个使用get_user_pages
(或get_page
)映射来自调用进程的页面的 Linux 驱动程序。然后将页面的物理地址传递给硬件设备。进程和设备都可以读取和写入页面,直到双方决定结束通信。特别是,在调用get_user_pages
返回的系统调用之后,通信可以继续使用页面。系统调用实际上是在进程和硬件设备之间建立一个共享内存区域。
我担心如果进程调用会发生什么fork
(它可能来自另一个线程,并且可能在调用的系统调用get_user_pages
正在进行或稍后发生)。特别是,如果父级在分叉之后写入共享内存区域,我对底层物理地址了解多少(可能由于写时复制而改变)?我想了解:
- 内核需要做什么来防御潜在的行为不端的进程(我不想造成安全漏洞!);
进程需要遵守哪些限制才能使我们的驱动程序的功能正常工作(即物理内存保持映射到父进程中的相同地址)。
- 理想情况下,我希望子进程根本不使用我们的驱动程序(它可能
exec
几乎立即调用)来工作的常见情况。 - 理想情况下,父进程在分配内存时不必采取任何特殊步骤,因为我们有现有代码将堆栈分配的缓冲区传递给驱动程序。
- 我知道
madvise
withMADV_DONTFORK
,可以让内存从子进程的空间中消失,但它不适用于堆栈分配的缓冲区。 - “当你与我们的司机有连接时不要使用叉子”会很烦人,但如果满足第 1 点,作为最后的手段是可以接受的。
- 理想情况下,我希望子进程根本不使用我们的驱动程序(它可能
我愿意被指向文档或源代码。我特别查看了Linux Device Drivers,但没有发现这个问题得到解决。即使只是应用于内核源代码的相关部分的 RTFS 也有点让人不知所措。
内核版本不是完全固定的,而是最近的版本(比方说≥2.6.26)。我们只针对 Arm 平台(目前是单处理器,但多核指日可待),如果重要的话。