我已经学习了如何将共享内存实现为两个用户模式进程之间的通信方法。但是我很好奇内核用户模式通信如何完成。
我想知道是否可以在不创建系统线程的情况下实现通过使用共享内存(根本不使用IOCTL!)的内核模式和用户模式之间的通信。
更新:例如,用户模式程序或内核模式驱动程序在内存中分配一个空间,并且两者都使用此空间在指针的帮助下进行通信。
使用共享内存进行通信的问题之一是与调度程序之间没有合作。特别; 在数据到达/更改之前,没有办法阻止任务(因此它不占用CPU时间),然后在数据到达/更改时取消阻止。
对于用户空间和内核之间的通信,您将遇到相同的问题。例如,用户空间代码修改了“与内核共享”内存中的数据,内核不知道是否/何时发生;因此(为了避免内核浪费CPU时间不断轮询共享内存),用户空间代码必须使用普通的内核调用说“嘿,现在看共享内存!”,但是如果您使用的是普通内核调用无论如何,您可以不使用共享内存就将数据传递一个指针。
使用共享内存进行通信的另一个问题是安全风险。具体来说,任务可以看到数据已到达/已更改,请验证新数据以确保其可接受,然后恶意攻击者可以在数据经过验证后更改数据,然后任务可以对“已验证”的数据进行操作。一个非常简单的示例就是“ if(new_value_in_shared_memory < MAX_VALUE) { myPrivateArray[new_value_in_shared_memory]++;
”之类的东西(恶意攻击者new_value_in_shared_memory
在被检查之后会发生变化,从而诱使任务修改它不应该进行的修改)。对于彼此信任的任务(例如,与fork()
就其本身而言)根本不是问题;当参与者之间彼此不信任(例如内核不信任用户空间代码)时,这将是一个巨大的痛苦(犯错误并被当成是极其容易的)。防范这种攻击的最简单方法是将数据从共享内存复制到专用缓冲区中,然后进行验证(知道攻击者无法修改副本),然后对副本中的数据进行操作。这种复制会增加开销,并且几乎破坏了共享内存的任何性能优势。
对于“与内核进行用户空间通信”的情况,有几种可能的选择-内核可以在“验证然后使用”阶段挂起所有可以访问共享内存的线程(这会造成性能损失,尤其是对于CPU系统);并且内核可以在“验证然后使用”阶段(例如,对于多线程环境而言,这将是性能灾难)在执行“虚拟然后再使用”阶段进行虚拟内存管理的技巧(例如,将基础页面设置为“如果用户空间试图对其进行修改,则为页面错误”状态)。 -CPU系统)。
请注意,对于“内核调用接受指向来自用户空间的数据的指针”和“内核调用依赖于来自用户空间任务的堆栈的数据”,会发生相同类型的“验证后修改”安全风险。然而; 对于这两种情况(不涉及共享内存,但涉及“内核访问任务的常规内存”),通常内核实际上并不访问数据,而只是传输数据。例如,对于一个write()
内核,内核可能会将数据转发到文件系统代码(而不涉及数据本身),后者可能会将数据转发到存储设备驱动程序(而无需涉及数据本身),后者可能会将数据传输到硬盘驱动器(无需触摸数据本身)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句