共享内存性能和对其他进程的保护
shared memory performance and protection from other processes
我正在尝试实现一个 JIT 编译器(我有非常古怪的爱好)。
我想要一个主进程来保存一些持久变量,第二个进程(已被即时编译)进行一些计算并可以访问和写入持久变量。
第二个进程可以更改和重新编译,但持久变量必须在第二个进程的两次执行之间保持相同。
我的第一个问题是:共享内存是合适的工具吗? (还有性能方面,因为我希望执行的越快越好。)
我的第二个问题是:如果我使用 shm_overview.7 中描述的共享内存,在我看来任何其他具有相同 uid 的进程都可以访问它。我该如何预防?我希望只有上述两个进程能够访问此共享内存。
是的,共享内存是一个合适的工具。
它的行为(从大局看)有点像一个文件
进程可以读取和写入,不同之处在于:
- 共享内存会更有效率,而且
- 共享内存将无法在重启后继续存在。
我不知道有什么固定的方法可以限制共享内存段
仅选定的进程,不包括具有相同 UID 的其他进程。
一般来说,如果你拥有某样东西,你就可以完全控制它,
并且具有相同 UID 的进程具有相同的访问权限*。
但是,如果您使用 shmget
创建共享内存段
使用 IPC_PRIVATE
作为键,
不相关的进程会更难找到。
它只能通过其 id
(标识符)访问,
其中 shmget
returns。对于其他一些找到 id
的进程,
它需要 运行 ipcs
并解析输出。然而,
您需要一种方法使 id
可用于您的第二个进程
(及时编译的那个);
可能作为参数或环境变量。
_______________
* 除了不同的 GID 或组成员身份导致的访问差异外
I would like only the two above processes to be able to access this
shared memory.
这真的不可能。除非你求助于一些额外的安全框架(grsecurity, SELinux,以及他们的朋友),否则标准 UNIX 环境定义的权限是这样的,另一个进程 运行 相同的 UID 可以完全控制你的进程,包括 stopping/restarting, killing, tracing, 检查和修改全进程内存。因此,即使您设法以某种方式从标准 SHM 访问中隐藏共享内存,您也无法完全阻止其他进程的干扰。
您可能会考虑的另一种架构是动态加载。您只有第一个,而不是两个过程;它使用 dlopen()
加载新编译的代码。它调用此 "library" 的入口点,代码可以访问所有 space,包括持久变量。在 return,您卸载库,为下一个 "run" 做好准备。
创建这样一个可加载库并调用它相当简单,而且比执行一个全新的进程要快。权限没有问题,因为您的唯一进程决定加载什么和 运行.
我正在尝试实现一个 JIT 编译器(我有非常古怪的爱好)。
我想要一个主进程来保存一些持久变量,第二个进程(已被即时编译)进行一些计算并可以访问和写入持久变量。
第二个进程可以更改和重新编译,但持久变量必须在第二个进程的两次执行之间保持相同。
我的第一个问题是:共享内存是合适的工具吗? (还有性能方面,因为我希望执行的越快越好。)
我的第二个问题是:如果我使用 shm_overview.7 中描述的共享内存,在我看来任何其他具有相同 uid 的进程都可以访问它。我该如何预防?我希望只有上述两个进程能够访问此共享内存。
是的,共享内存是一个合适的工具。 它的行为(从大局看)有点像一个文件 进程可以读取和写入,不同之处在于:
- 共享内存会更有效率,而且
- 共享内存将无法在重启后继续存在。
我不知道有什么固定的方法可以限制共享内存段 仅选定的进程,不包括具有相同 UID 的其他进程。 一般来说,如果你拥有某样东西,你就可以完全控制它, 并且具有相同 UID 的进程具有相同的访问权限*。 但是,如果您使用
shmget
创建共享内存段 使用IPC_PRIVATE
作为键, 不相关的进程会更难找到。 它只能通过其id
(标识符)访问, 其中shmget
returns。对于其他一些找到id
的进程, 它需要 运行ipcs
并解析输出。然而, 您需要一种方法使id
可用于您的第二个进程 (及时编译的那个); 可能作为参数或环境变量。
_______________
* 除了不同的 GID 或组成员身份导致的访问差异外
I would like only the two above processes to be able to access this shared memory.
这真的不可能。除非你求助于一些额外的安全框架(grsecurity, SELinux,以及他们的朋友),否则标准 UNIX 环境定义的权限是这样的,另一个进程 运行 相同的 UID 可以完全控制你的进程,包括 stopping/restarting, killing, tracing, 检查和修改全进程内存。因此,即使您设法以某种方式从标准 SHM 访问中隐藏共享内存,您也无法完全阻止其他进程的干扰。
您可能会考虑的另一种架构是动态加载。您只有第一个,而不是两个过程;它使用 dlopen()
加载新编译的代码。它调用此 "library" 的入口点,代码可以访问所有 space,包括持久变量。在 return,您卸载库,为下一个 "run" 做好准备。
创建这样一个可加载库并调用它相当简单,而且比执行一个全新的进程要快。权限没有问题,因为您的唯一进程决定加载什么和 运行.