#共享内存 #shmem #api-bindings #共享内存

shmem-bind

在Rust中对共享内存API的安全且惯用的封装,具有适当的清理功能

4个版本

0.1.3 2024年3月20日
0.1.2 2024年3月19日
0.1.1 2024年3月19日
0.1.0 2024年3月18日

3 in #shmem

Download history 17/week @ 2024-04-02 2/week @ 2024-05-28

每月110次下载

MIT/Apache

20KB
186

shmem-bind

在Rust中对共享内存API的安全且惯用的封装,具有适当的清理功能。

快速入门

查看message-passing示例以更好地理解

cargo run --example message-passing

语义

分配

导入共享内存抽象

use shmem_bind::{ShmemBox, self as shmem};

为了创建新的共享内存,使用以下构建器代码片段

let shared_mem = shmem::Builder::new("<FLINK_FILE_HANDLE>")
    .with_size(mem::size_of::<MyType>() as i64)
    .open()?;

如果机器上不存在共享内存,这将分配指定大小的共享内存文件。这里的手柄shared_mem将声明对共享内存的所有权,如果共享内存不存在并且通过调用open函数创建,这是清理过程的有用信息,因为每个共享内存只有一个所有者,并且只有所有者才能解除链接共享内存。

您可以通过调用boxed函数将共享内存配置包装到ShmemBox<T>中。

let boxed_val = unsafe { shared_mem.boxed::<MyType>() };

调用此函数本质上是不安全的,因为没有保证指针后面的内存已初始化或有效。

type NotZeroI32 = i32;

let boxed_val = unsafe { 
  // the allocated shared_memory is zeroed and thus, not a valid `NotZeroI32`
  let mut boxed_val = shared_mem.boxed::<NotZeroI32>();
  *boxed_val = 5;
  boxed_val
  };

ShmemBox类型实现了DerefDerefMut,因此您可以在代码中使用所有Rust语义和T的保证

清理

当变量超出作用域时,会调用drop实现。如果共享内存是所有者,即共享内存是由此句柄创建的,则共享内存将解除链接。为了防止这种情况,您可以使用ShmemBox::leak方法


struct MyType;

impl Drop for MyType{
    fn drop(&mut self) {
        println!("my type is dropped");
    }
}

{
  let shared_mem = shmem::Builder::new("<FLINK_FILE_HANDLE>")
      .with_size(mem::size_of::<Message>() as i64)
      .open()?;
  let mut boxed_val = unsafe {shared_mem.boxed::<MyType>()};

  // boxed_val goes out of scope and the underlying MyType is dropped
  // output:
  // my type is dropped
}
{
  let shared_mem = shmem::Builder::new("<FLINK_FILE_HANDLE>")
      .with_size(mem::size_of::<Message>() as i64)
      .open()?;
  let mut boxed_val = unsafe {shared_mem.boxed::<MyType>()};
  ShmemBox::leak(boxed_val);

  // boxed_val leaks and the underlying MyType is not dropped. the shared memory stays linked to the os
  // output is empty
}

您还可以使用ShmemBox::own来确保共享内存的清理

struct MyType;

impl Drop for MyType{
    fn drop(&mut self) {
        println!("my type is dropped");
    }
}

{
  let shared_mem = shmem::Builder::new("<FLINK_FILE_HANDLE>")
      .with_size(mem::size_of::<Message>() as i64)
      .open()?;
  let mut boxed_val = unsafe {shared_mem.boxed::<MyType>()};
  
  // boxed_val was owner, but it got leaked
  ShmemBox::leak(boxed_val);
}
{
  let shared_mem = shmem::Builder::new("<FLINK_FILE_HANDLE>")
      .with_size(mem::size_of::<Message>() as i64)
      .open()?;
  let mut boxed_val = unsafe {shared_mem.boxed::<MyType>()};
  
  // shared memory is already created, so the boxed_val is not the owner.
  let boxed_val = ShmemBox::own(boxed_val);

  // boxed_val goes out of scope, MyType is dropped. the shared memory is unliked.
  // output:
  // my type is dropped
}

ShmemBox<T>实现SyncSend,如果底层的T分别实现了SyncSend

依赖项

~43KB