目录
1. 操作系统原语绑定
Rust 通过 libc/winapi crate 直接调用操作系统 API:
use libc::{open, O_RDONLY, read, close};
use std::os::raw::c_void;
fn raw_read(path: &str) -> Result<Vec<u8>, i32> {
let fd = unsafe {
let c_path = std::ffi::CString::new(path).unwrap();
open(c_path.as_ptr(), O_RDONLY)
};
if fd < 0 {
return Err(unsafe { *libc::__errno_location() });
}
let mut buf = vec![0u8; 4096];
let n = unsafe { read(fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
unsafe { close(fd); }
buf.truncate(n as usize);
Ok(buf)
}
nix crate:安全的系统调用封装
use nix::unistd::{fork, ForkResult, execvp};
use nix::sys::wait::waitpid;
match unsafe { fork() } {
Ok(ForkResult::Child) => {
execvp(&"ls".into(), &["ls".into(), "-la".into()]).unwrap();
}
Ok(ForkResult::Parent { child }) => {
waitpid(child, None).unwrap();
}
Err(_) => eprintln!("Fork failed"),
}
2. 零拷贝 I/O
2.1 sendfile 系统调用
use nix::sys::sendfile::sendfile;
fn send_file(src: RawFd, dest: RawFd, offset: off_t, count: size_t) -> Result<ssize_t> {
let mut off = offset;
sendfile(dest, src, Some(&mut off), count)
}
2.2 splice(管道零拷贝)
use nix::fcntl::{splice, SpliceFFlags};
// 将数据从文件 splice 到 socket,不经过用户空间
splice(
file_fd, None,
socket_fd, None,
4096,
SpliceFFlags::empty(),
)?;
2.3 io_uring(Linux 异步 I/O)
use io_uring::{IoUring, opcode, types};
let mut ring = IoUring::new(32)?;
// 提交读请求
let read_e = opcode::Read::new(fd, buf.as_mut_ptr(), buf.len() as u32)
.build()
.user_data(0x42);
unsafe {
ring.submission()
.push(&read_e)
.expect("submission queue full");
}
ring.submit_and_wait(1)?;
3. 内存映射 mmap
3.1 文件映射
use memmap2::MmapOptions;
use std::fs::File;
let file = File::open("large.bin")?;
let mmap = unsafe { MmapOptions::new().map(&file)? };
// 像访问内存一样访问文件,不占用堆内存
println!("First byte: {}", mmap[0]);
3.2 匿名映射(共享内存)
let mut mmap = MmapOptions::new()
.len(4096)
.map_mut()?;
mmap[..5].copy_from_slice(b"hello");
3.3 跨进程共享内存
use memmap2::MmapMut;
use std::fs::OpenOptions;
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open("/dev/shm/my_shared_mem")?;
file.set_len(4096)?;
let mut mmap = unsafe { MmapMut::map_mut(&file)? };
mmap[..13].copy_from_slice(b"Hello Process");
4. 性能剖析工具链
4.1 cargo flamegraph
cargo install flamegraph
# 生成 CPU 火焰图(需 sudo 或在 Linux 上)
cargo flamegraph --bin myapp
# 打开 flamegraph.svg 查看热点
4.2 perf + cargo-profiler
# Linux perf
cargo build --release
perf record -g ./target/release/myapp
perf report
# cargo-profiler(callgrind/cachegrind)
cargo install cargo-profiler
cargo profiler callgrind --bin myapp
4.3 tokio-console
# 查看异步任务状态
cargo install tokio-console
# 代码中添加 ConsoleLayer
use console_subscriber::ConsoleLayer;
ConsoleLayer::builder().init();
# 运行
tokio-console
5. 编译器优化
5.1 Cargo.toml 优化配置
[profile.release]
opt-level = 3 # 最高优化级别
lto = true # 链接时优化
strip = true # 移除符号表,减小体积
panic = "abort" # panic 时直接 abort,不移栈
codegen-units = 1 # 减少并行编译单元,提升优化机会
[profile.release.build-override]
opt-level = 3
5.2 PGO(Profile Guided Optimization)
# 1. 编译插桩版本
RUSTFLAGS="-Cprofile-generate=/tmp/pgo" cargo build --release
# 2. 运行代表性负载
./target/release/myapp --benchmark
# 3. 合并 profile
llvm-profdata merge -o /tmp/pgo/merged.profdata /tmp/pgo
# 4. 再编译优化版本
RUSTFLAGS="-Cprofile-use=/tmp/pgo/merged.profdata" cargo build --release
5.3 target-cpu 特定优化
# 针对当前 CPU 架构优化
RUSTFLAGS="-C target-cpu=native" cargo build --release
# 针对特定架构(如 Apple M3)
RUSTFLAGS="-C target-cpu=apple-m3" cargo build --release
6. Benchmark 实践
6.1 Criterion.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn fibonacci(n: u64) -> u64 {
match n {
0 => 1,
1 => 1,
n => fibonacci(n - 1) + fibonacci(n - 2),
}
}
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
cargo bench
6.2 内存分配基准
use stats_alloc::{StatsAlloc, Region, INSTRUMENTED_SYSTEM};
use std::alloc::System;
#[global_allocator]
static GLOBAL: StatsAlloc<System> = INSTRUMENTED_SYSTEM;
#[test]
fn test_allocations() {
let reg = Region::new(&GLOBAL);
let _ = process_data();
let stats = reg.change();
assert_eq!(stats.bytes_allocated, 1024);
assert_eq!(stats.bytes_deallocated, 1024);
}
6.3 Iai(指令计数基准)
use iai::black_box;
fn iai_benchmark() {
black_box(fibonacci(black_box(20)));
}
iai::main!(iai_benchmark);
7. 内存分析
7.1 dhat(堆分配追踪)
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;
fn main() {
let _profiler = dhat::Profiler::new_heap();
// 运行程序...
}
7.2 cargo bloat(查看二进制体积构成)
cargo install cargo-bloat
# 按大小排序的符号
cargo bloat --release -n 20
# 按 crate 分组
cargo bloat --release --crates
7.3 cargo audit(依赖安全检查)
cargo install cargo-audit
cargo audit
8. no_std 系统编程
8.1 自定义分配器
use core::alloc::{GlobalAlloc, Layout};
struct MyAllocator;
unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
libc::malloc(layout.size()) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
libc::free(ptr as *mut libc::c_void);
}
}
#[global_allocator]
static ALLOCATOR: MyAllocator = MyAllocator;
8.2 内核模块编程
#![no_std]
#![no_main]
use linux_kernel_module::{self, println};
module! {
type: MyModule,
name: b"my_kernel_module",
author: b"Developer",
description: b"A sample module",
license: b"GPL",
}
struct MyModule;
impl linux_kernel_module::KernelModule for MyModule {
fn init() -> Result<Self, linux_kernel_module::Error> {
println!("Hello from kernel module!");
Ok(MyModule)
}
}
Rust 在系统编程领域的独特价值:零成本抽象让高级代码编译后不输手写 C,所有权系统消除整类内存错误,现代工具链(cargo/flamegraph/profiler)让性能分析前所未有的简单。从用户态到内核态,从边缘设备到数据中心,Rust 正在重塑系统软件的编写方式。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。
「rust」更多文章
Rust 错误处理与测试:thiserror、mockall 与属性测试
Rust 错误处理最佳实践:Result/Option 组合子、thiserror 与 anyhow 选型、panic 边界控制、单元/集成/文档测试、mockall 模拟、property-based testing 与代码覆盖率。
Rust 桌面端与 WASM:Tauri、WebAssembly 与嵌入式开发
Rust 跨平台开发全景:Tauri 替代 Electron 的轻量级架构、WASM 编译(wasm-bindgen/wasm-pack)、WASI 运行时、嵌入式 Rust(no_std/embedded-hal),以及跨平台发布策略。
Rust 核心概念详解:所有权、Trait 与宏系统
Rust 核心概念全景解析:所有权模型、借用检查器、生命周期、Trait 系统、泛型编程、声明宏与过程宏,以及 Cargo 工作区与 crates 生态体系。