从文件中读取原始结构的最佳方法

卡森

背景(可跳过)

在 linux 上,该文件/var/run/utmp包含几个utmp结构,每个结构都是原始二进制格式,在一个文件中彼此跟随。utmp本身是一个比较大的(在我的机器上是 384 字节)。我正在尝试将此文件读取为原始数据,并在数据有意义后实施检查。我对 rust 并不陌生,但这是我第一次真正体验到事物不安全的一面。

问题陈述

我有一个包含多个 c sturct utmps ( docs ) 的文件。在 rust 中,我想将整个文件读入一个Vec<libc::utmpx>. 更具体地说,给定一个阅读器打开这个文件,我怎么能阅读一个struct utmp

到目前为止我所拥有的

以下是 的三种不同实现read_raw,它们接受一个阅读器并返回一个RawEntry(我的别名struct utmp)。哪种方法最正确?我正在尝试编写尽可能高性能的代码,我担心read_raw0如果涉及 memcpys 可能会比其他代码慢。完成此行为的最佳/最快方法是什么?

use std::io::Read;
use libc::utmpx as RawEntry;

const RawEntrySize = std::mem::size_of::<RawEntry>();
type RawEntryBuffer = [u8; RawEntrySize];

/// Read a raw utmpx struct
// After testing, this method doesn't work
pub fn read_raw0<R: Read>(reader: &mut R) -> RawEntry {
    let mut entry: RawEntry = unsafe { std::mem::zeroed() };
    unsafe {
        let mut entry_buf = std::mem::transmute::<RawEntry, RawEntryBuffer>(entry);
        reader.read_exact(&mut entry_buf[..]);
    }
    return entry;
}

/// Read a raw utmpx struct
pub fn read_raw1<R: Read>(reader: &mut R) -> RawEntry {
    // Worried this could cause alignment issues, or maybe it's okay 
    // because transmute copies
    let mut buffer: RawEntryBuffer = [0; RawEntrySize];
    reader.read_exact(&mut buffer[..]);
    let entry = unsafe {
        std::mem::transmute::<RawEntryBuffer, RawEntry>(buffer)
    };
    return entry;
}

/// Read a raw utmpx struct
pub fn read_raw2<R: Read>(reader: &mut R) -> RawEntry {
    let mut entry: RawEntry = unsafe { std::mem::zeroed() };
    unsafe {
        let entry_ptr = std::mem::transmute::<&mut RawEntry, *mut u8>(&mut entry);
        let entry_slice = std::slice::from_raw_parts_mut(entry_ptr, RawEntrySize);
        reader.read_exact(entry_slice);
    }
    return entry;
}

注意:经过更多测试,它似乎read_raw0不起作用。我相信这是因为 transmute 创建了一个新缓冲区而不是引用结构。

洛克

这就是我想出的,我想它应该与读取单个条目一样快。它遵循您上一个条目的精神,但避免了转换(转换&mut T*mut u8可以通过两次强制转换来完成:)t as *mut T as *mut u8此外,它使用MaybeUninit而不是zeroed更明确(程序集在优化后可能相同)。最后,无论哪种方式,该功能都是不安全的,因此我们不妨将其标记为这样并取消unsafe块。

use std::io::{self, Read};
use std::slice::from_raw_parts_mut;
use std::mem::{MaybeUninit, size_of};

pub unsafe fn read_raw_struct<R: Read, T: Sized>(src: &mut R) -> io::Result<T> {
    let mut buffer = MaybeUninit::uninit();
    let buffer_slice = from_raw_parts_mut(buffer.as_mut_ptr() as *mut u8, size_of::<T>());
    
    src.read_exact(buffer_slice)?;
    Ok(buffer.assume_init())
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从文件中读取数组的最佳方法

从包含IP标头片段的二进制文件中读取结构的最佳方法是什么?

在 Java 中读取字符块中的文件的最佳方法

在Visual Studio中创建相同文件结构的最佳方法

读取文件列表的最佳方法

从文件中读取原始字节数据并将其解码为 protobuf 结构

在bash中读取配置文件的最佳方法

用Java读取结构化二进制文件的最佳方法

在结构中处理结构数组的最佳方法

从Java中的结构化原始文件创建json文件的最简单方法?

在 Pandas 中读取原始 Json 文件

读取配置文件的最佳方法

编写从文件读取的循环的最佳方法是哪种?

Python:逐行读取文件的最佳方法

在QML中访问cpp结构的最佳方法

修改结构中数组的最佳方法?

如何从Rust中的文件读取结构?

如何使用结构从文件中读取?

读取Java中的结构化文件

在C中从文件读取数据到结构

使用CRTP从文件中读取结构

如何从原始文件夹中读取某些文件?

在Aerospike中实现批量读取的最佳方法

读取Java IO中包含单行字符串的大文件的最佳方法

在 Python 中读取具有不同类型值的文本文件的最佳方法

从Java中的配置文件读取配置参数的最佳方法是什么?

在Java应用程序中读取XML文件的最佳/最简单方法是什么?

在Java中读取文本文件的最后一行的最佳方法是什么?

在具有以下条件的文件中读取/写入对象的最佳方法是什么