当前位置: 首页 > 知识库问答 >
问题:

如何使用memmap板条箱附加到文件支持的mmap?

姚嘉容
2023-03-14

我有一个文件foo.txt的内容

foobar

我想连续附加到这个文件并有权访问修改后的文件。

我尝试的第一件事是直接变异mmap:

use memmap;
use std::fs;
use std::io::prelude::*;

fn main() -> Result<(), Box<std::error::Error>> {
    let backing_file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .write(true)
        .open("foo.txt")?;

    let mut mmap = unsafe { memmap::MmapMut::map_mut(&backing_file)? };

    loop {
        println!("{}", std::str::from_utf8(&mmap[..])?);
        std::thread::sleep(std::time::Duration::from_secs(5));
        let buf = b"somestring";
        (&mut mmap[..]).write_all(buf)?;
        mmap.flush()?;
    }
}

这将导致恐慌:

Error: Custom { kind: WriteZero, error: StringError("failed to write whole buffer") }

生成的文件读取Somest

之后,我尝试直接附加到后备文件:

use memmap;
use std::fs;
use std::io::prelude::*;

fn main() -> Result<(), Box<std::error::Error>> {
    let mut backing_file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .write(true)
        .open("foo.txt")?;

    let mmap = unsafe { memmap::MmapMut::map_mut(&backing_file)? };

    loop {
        println!("{}", std::str::from_utf8(&mmap[..])?);
        std::thread::sleep(std::time::Duration::from_secs(5));
        let buf = b"somestring";
        backing_file.write_all(buf)?;
        backing_file.flush()?;
    }
}

这不会导致恐慌。该文件将定期更新,但我的mmap不会反映这些更改。我预计标准输出如下所示:

foobar
foobarsomestring
foobarsomestringsomestring
...

但我有

foobar
foobar
foobar
...

我主要对一个Linux的解决方案感兴趣,如果它依赖于平台。

共有1个答案

宋英杰
2023-03-14

首先,根据我的理解,我希望你们对那个板条箱高度怀疑。它允许你在安全的环境下做你不应该做的事情。

例如,如果您有一个文件支持的mmap,那么计算机上对该文件具有正确权限的任何进程都可以修改它。这意味着:

  1. 将MMMapped文件视为不可变的字节片(

该板条箱的文档没有涵盖所有这些问题,也没有讨论如何以安全的方式使用少数不安全的功能。对我来说,这些迹象表明,您可能在代码中引入了未定义的行为,这是一件非常糟糕的事情。

例如:

use memmap;
use std::{fs, io::prelude::*};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut backing_file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .write(true)
        .open("foo.txt")?;

    backing_file.write_all(b"initial")?;

    let mut mmap_mut = unsafe { memmap::MmapMut::map_mut(&backing_file)? };
    let mmap_immut = unsafe { memmap::Mmap::map(&backing_file)? };

    // Code after here violates the rules of references, but doesn't use `unsafe`
    let a_str: &str = std::str::from_utf8(&mmap_immut)?;
    println!("{}", a_str); // initial

    mmap_mut[0] = b'x';

    // Look, we just changed an "immutable reference"!
    println!("{}", a_str); // xnitial

    Ok(())
}

由于人们通常不喜欢被告知“不,不要这样做,这是个坏主意”,以下是如何让您的代码“工作”:直接附加到文件中,然后重新创建mmap:

use memmap;
use std::{fs, io::prelude::*, thread, time::Duration};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut backing_file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .write(true)
        .open("foo.txt")?;

    // mmap requires that the initial mapping be non-zero
    backing_file.write_all(b"initial")?;

    for _ in 0..3 {
        let mmap = unsafe { memmap::MmapMut::map_mut(&backing_file)? };

        // I think this line can introduce memory unsafety
        println!("{}", std::str::from_utf8(&mmap[..])?);

        thread::sleep(Duration::from_secs(1));

        backing_file.write_all(b"somestring")?;
    }

    Ok(())
}

你可能想在这个文件中预先分配一大块空间,这样你就可以打开它开始写,而不必重新映射它。

我不会将此代码用于数据正确性很重要的任何事情。

另见:

  • 附加到Mmap编辑的文件是否安全且跨平台?
  • 附加到内存映射文件
  • 如何创建和写入内存映射文件?

 类似资料:
  • 如何使用pyarrow向拼花地板文件添加/更新? 我在文档中找不到任何关于附加拼花文件的内容。此外,您是否可以将pyarrow与多处理一起使用来插入/更新数据。

  • 问题内容: 我正在写某种生成加密日志文件的记录器。不幸的是,密码学不是我的强项。现在,我可以向文件写入几条消息,然后关闭文件。然后我可以打开它,附加一些消息,再次关闭,解密后,我在文件中间看到填充字节。有什么方法可以处理加密文件,而不必每次我想添加一些消息时都对其解密? 编辑 :更多细节。当前实现使用CipherOutputStream。据我了解,没有办法 寻求 使用它。如果我将控制输出数据大小可

  • 问题内容: 我试图将滚动条附加到“文本”字段,但无法这样做。这是代码段: 这段代码在我的文本字段旁边放置了一个非常小的滚动条(并且非常小,我的意思是您可以看到向上和向下箭头,但中间没有看到)。当文本字段填满时,我可以使用它滚动,但是至少有一种方法可以设置滚动条的高度,以使其看起来与文本字段的高度相同吗? 问题答案: Tkinter具有三个 几何管理器 :包装,网格和位置。 通常建议将包装和网格放在

  • 问题内容: 在Linux中将文本附加到文件的最简单方法是什么? 我看了这个问题,但是可接受的答案使用了一个附加程序(),我相信应该有一个更简单的方法或类似方法。 问题答案: cat >> filename This is text, perhaps pasted in from some other source. Or else entered at the keyboard, doesn’t

  • 有没有办法将文件附加到MS Word文档中?我的意思与您将MS Excel文件拖放到MS Word中的方式相同。它显示MS Excel图标和文件名,双击打开附件。 我的情况来自以前的html文件,我导入使用XHTMLImporter.convert.现在超文本标记语言引用附件下载几个地方,并希望将这些文件附加到适当的MS Word文档。

  • 问题内容: 我该怎么做才能将其附加到文件中而不是覆盖? 问题答案: 使用附加: