如何通过shm_open写入共享内存?
How to write to shared memory via shm_open?
我需要在 C 和 Rust 应用程序之间共享内存。
Rust - 生产者,C - 消费者。
在 C 中,我会创建一个共享内存区域并将其传递给 Rust 进行写入。
在 C 端我使用这样的东西:
fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
res = ftruncate(fd, STORAGE_SIZE);
addr = mmap(NULL, STORAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
// read from that memory after it is written by Rust app
char data[STORAGE_SIZE];
memcpy(data, addr, STORAGE_SIZE);
我在 Rust 端如何使用 STORAGE_ID 打开内存并写入?
我想它是沿着这条线使用的,但找不到可靠的例子:
https://docs.rs/libc/0.2.77/libc/fn.shm_open.html
https://docs.rs/memmap/0.6.1/memmap/struct.Mmap.html
https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice
基本上,我需要做这样的事情,但是 set.c 用 Rust 写的:
POSIX shared memory IPC example (shm_open, mmap), working on Linux and macOS
使用 Rust 的 libc
crate,我们可以访问 C 进程可以访问的相同函数,因此 Rust 中的代码看起来与您在 C 中编写生产者时所编写的代码非常相似.
下面的代码演示了作为生产者和消费者的 Rust 代码。生产者和消费者以这种方式组合只是为了有一个简单的例子,可以从命令行 运行 验证 Rust 生产者代码的工作。
在下面的代码中,main()
函数顶部的代码块与问题 post 中的代码相同。消费者和生产者都执行此操作以获取共享内存区域。
if
块的第一个分支将原始进程设置为消费者,它启动具有相同可执行文件的 child 进程。 child 的执行路径将遵循 else
分支并写入共享内存区域。
parent 阻塞直到 child 完成,然后读取共享内存区域并打印它。
use libc::{close, ftruncate, memcpy, mmap, shm_open, strncpy};
use libc::{MAP_SHARED, O_RDWR, O_CREAT, PROT_WRITE, S_IRUSR, S_IWUSR};
use libc::{c_char, c_void, off_t, size_t};
use std::{env, ptr, str};
use std::process::Command;
use std::error::Error;
const STORAGE_ID : *const c_char = b"MY_MEM_ID[=10=]".as_ptr() as *const c_char;
const STORAGE_SIZE : size_t = 128;
fn main() -> Result<(), Box<dyn Error>>
{
let args = env::args().collect::<Vec<_>>();
let (fd, addr) = unsafe {
let null = ptr::null_mut();
let fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
let _res = ftruncate(fd, STORAGE_SIZE as off_t);
let addr = mmap(null, STORAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
(fd, addr)
};
if args.len() == 1 {
// Consumer...
let exec_path = &args[0];
// Start producer process. Block until done.
let output = Command::new(exec_path).arg("Producer...").output()?;
println!("Producer stdout : {}", str::from_utf8(&output.stdout)?);
let mut data = [0_u8; STORAGE_SIZE];
let pdata = data.as_mut_ptr() as *mut c_char;
unsafe {
strncpy(pdata, addr as *const c_char, STORAGE_SIZE);
close(fd);
}
println!("Producer message : {}", str::from_utf8(&data)?);
} else {
// Producer...
let data = b"Hello, World![=10=]";
let pdata = data.as_ptr() as *const c_void;
unsafe {
memcpy(addr, pdata, data.len());
}
print!("Done.");
}
Ok(())
}
输出:
Producer stdout : Done.
Producer message : Hello, World!
我需要在 C 和 Rust 应用程序之间共享内存。 Rust - 生产者,C - 消费者。
在 C 中,我会创建一个共享内存区域并将其传递给 Rust 进行写入。
在 C 端我使用这样的东西:
fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
res = ftruncate(fd, STORAGE_SIZE);
addr = mmap(NULL, STORAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
// read from that memory after it is written by Rust app
char data[STORAGE_SIZE];
memcpy(data, addr, STORAGE_SIZE);
我在 Rust 端如何使用 STORAGE_ID 打开内存并写入? 我想它是沿着这条线使用的,但找不到可靠的例子:
https://docs.rs/libc/0.2.77/libc/fn.shm_open.html
https://docs.rs/memmap/0.6.1/memmap/struct.Mmap.html
https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice
基本上,我需要做这样的事情,但是 set.c 用 Rust 写的: POSIX shared memory IPC example (shm_open, mmap), working on Linux and macOS
使用 Rust 的 libc
crate,我们可以访问 C 进程可以访问的相同函数,因此 Rust 中的代码看起来与您在 C 中编写生产者时所编写的代码非常相似.
下面的代码演示了作为生产者和消费者的 Rust 代码。生产者和消费者以这种方式组合只是为了有一个简单的例子,可以从命令行 运行 验证 Rust 生产者代码的工作。
在下面的代码中,main()
函数顶部的代码块与问题 post 中的代码相同。消费者和生产者都执行此操作以获取共享内存区域。
if
块的第一个分支将原始进程设置为消费者,它启动具有相同可执行文件的 child 进程。 child 的执行路径将遵循 else
分支并写入共享内存区域。
parent 阻塞直到 child 完成,然后读取共享内存区域并打印它。
use libc::{close, ftruncate, memcpy, mmap, shm_open, strncpy};
use libc::{MAP_SHARED, O_RDWR, O_CREAT, PROT_WRITE, S_IRUSR, S_IWUSR};
use libc::{c_char, c_void, off_t, size_t};
use std::{env, ptr, str};
use std::process::Command;
use std::error::Error;
const STORAGE_ID : *const c_char = b"MY_MEM_ID[=10=]".as_ptr() as *const c_char;
const STORAGE_SIZE : size_t = 128;
fn main() -> Result<(), Box<dyn Error>>
{
let args = env::args().collect::<Vec<_>>();
let (fd, addr) = unsafe {
let null = ptr::null_mut();
let fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
let _res = ftruncate(fd, STORAGE_SIZE as off_t);
let addr = mmap(null, STORAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
(fd, addr)
};
if args.len() == 1 {
// Consumer...
let exec_path = &args[0];
// Start producer process. Block until done.
let output = Command::new(exec_path).arg("Producer...").output()?;
println!("Producer stdout : {}", str::from_utf8(&output.stdout)?);
let mut data = [0_u8; STORAGE_SIZE];
let pdata = data.as_mut_ptr() as *mut c_char;
unsafe {
strncpy(pdata, addr as *const c_char, STORAGE_SIZE);
close(fd);
}
println!("Producer message : {}", str::from_utf8(&data)?);
} else {
// Producer...
let data = b"Hello, World![=10=]";
let pdata = data.as_ptr() as *const c_void;
unsafe {
memcpy(addr, pdata, data.len());
}
print!("Done.");
}
Ok(())
}
输出:
Producer stdout : Done.
Producer message : Hello, World!