我目前正在构建一个内核模块,我想以一种非常理想的方式面对 SMP 问题。
目前,我有一组对象,每个对象都绑定到一个特定的 CPU。以下代码说明了这一点:
struct my_object {
int a_field;
};
struct my_object cpu_object[NR_CPUS];
/*
* cpu_object[i] is "bound" to CPU number "i" !
*/
一个简单的调用smp_processor_id()
就会给我当前代码正在运行的处理器。因此,如果我有一个foo
使用上述 CPU 绑定对象执行某些工作的函数,它可能看起来像:
void foo()
{
int cpu = smp_processor_id();
do_some_work_with(cpu_object[cpu]);
}
问题是:如何保证
cpu
分配和do_some_work_with
?之间没有 CPU 切换do_some_work_with()
只会运行cpu
吗?
当时,我想到的解决方案是:
- 使用自旋锁禁用抢占
- 获取 CPU
smp_processor_id
- 设置当前任务的处理器亲和性,使其与当前 CPU 保持一致
- 再次启用抢占,释放锁
- 做好工作
do_some_work_with()
- 将亲和力重置为之前的状态
对我来说,这是相当野蛮的,我想知道是否有更聪明、更轻松的方法来做到这一点。
提前致谢。
编辑:如评论中所述,我编辑以解释为什么我觉得我需要这些功能。我必须在文件系统级别执行动态加密。
为此,我将使用内核内置的加密支持(struct crypto_tfm
和朋友)。这是原始问题...
在多核机器上,可以同时执行多个 R/W 操作。常见的 fs 层可以做到这一点并且做得很好。但是,我来了,把事情搞砸了:
- 类
struct crypto_tfm
对象负责加密操作 - 不能同时使用相同的变换对象,因为某些参数会被更改(私钥和初始化向量)并破坏所有过程
- 由于加密中内置的复杂密码分配系统,下面描述的简单解决方案完全不可能。
- 分配
crypto_tfm
转换 - 执行加密操作
- 释放转换对象
- 分配
- 只有一个转换可用的经典方案可防止多个并发 R/W 操作,因为一个任务必须等待另一个任务释放持有的锁以保护转换对象。
由于这些原因,我需要处理多个转换对象。我必须找到一个允许并发 R/W 的有效方案。我觉得我的“Y”在这里是“简单、整洁......但错误的解决方案”。任何建议将不胜感激。
注意:如果我使用类似于我在原始问题中给出的解决方案,我会将其限制在非常短的部分,以避免对 CPU 负载平衡产生重大影响。