2015-02-14 22 views
11

Próbuję utworzyć plik odwzorowany w pamięci przy użyciu std::os::MemoryMap. Obecne podejście wygląda następująco:Jak tworzyć i zapisywać do plików mapowanych w pamięci?

use std::os; 
use std::ptr; 
use std::old_io as io; 
use std::os::unix::prelude::AsRawFd; 
use std::os::MapOption; 

let path = Path::new("test.mmap"); 

let f = match io::File::open_mode(&path, io::Open, io::ReadWrite) { 
    Ok(f) => f, 
    Err(err) => panic!("Could not open file: {}", err), 
}; 

let mmap_opts = &[ 
    MapOption::MapReadable, 
    MapOption::MapWritable, 
    MapOption::MapFd(f.as_raw_fd()) 
]; 

let mmap = match os::MemoryMap::new(1024*1024, mmap_opts) { 
    Ok(mmap) => { 
     println!("Successfully created the mmap: {}", mmap.len()); 
     mmap 
    } 
    Err(err) => panic!("Could not read the mmap: {}", err), 
}; 

unsafe { 
    let data = mmap.data(); 

    if data.is_null() { 
     panic!("Could not access data from memory mapped file") 
    } 

    let src = "Hello!"; 
    ptr::copy_memory(data, src.as_ptr(), src.as_bytes().len()); 
} 

Ten program nie działa z

Process didn't exit successfully: `target/mmap` (status=4) 

Dzwoniąc ptr::copy_memory lub wszelkie inne operacje na danych.

  • Z jakiego powodu nie mogę zapisać (lub odczytać) danych z MemoryMap?
  • Jaki jest poprawny sposób użycia MemoryMap w rdzy?
+3

Co masz na myśli mówiąc "nie powiedzie się, gdy dzwoni ..."? Czy jest błąd kompilatora, awarie w czasie wykonywania, jaki jest komunikat o błędzie itp.? – delnan

+0

Czy chcesz, aby modyfikacje zostały ponownie zapisane w pliku? – Shepmaster

+0

@delnan, zaktualizowano pytanie z komunikatem o błędzie – mkhq

Odpowiedz

10

Brakuje dwóch głównych części:

  1. mmapdoesn't allocate any space on its own, więc trzeba ustawić trochę miejsca w pliku. Bez tego, mam Illegal instruction: 4 gdy działa na OS X.

  2. MemoryMap jest private by default więc trzeba zaznaczyć mapowanie jako publicznej tak, że zmiany są zapisywane do pliku (jestem zakładając chcesz, pisze do uratować się). Bez tego kod działa, ale plik nigdy się nie zmienia.

Oto wersja, która działa dla mnie:

#![feature(path,io,os,std_misc,core,libc)] 

use std::os; 
use std::ptr; 
use std::old_io as io; 
use std::os::unix::prelude::AsRawFd; 
use std::os::MapOption; 

extern crate libc; 

fn main() { 
    let size = 1024*1024; 

    let path = Path::new("test.mmap"); 
    let mut f = io::File::open_mode(&path, io::Open, io::ReadWrite).unwrap(); 

    // Allocate space in the file first 
    f.seek(size as i64, io::SeekStyle::SeekSet).unwrap(); 
    f.write_u8(0).unwrap(); 
    f.seek(0, io::SeekStyle::SeekSet).unwrap(); 

    let mmap_opts = &[ 
     // Then make the mapping *public* so it is written back to the file 
     MapOption::MapNonStandardFlags(libc::consts::os::posix88::MAP_SHARED), 
     MapOption::MapReadable, 
     MapOption::MapWritable, 
     MapOption::MapFd(f.as_raw_fd()), 
    ]; 

    let mmap = os::MemoryMap::new(size, mmap_opts).unwrap(); 

    let data = mmap.data(); 

    if data.is_null() { 
     panic!("Could not access data from memory mapped file") 
    } 

    let src = "Hello!"; 
    let src_data = src.as_bytes(); 

    unsafe { 
     ptr::copy_memory(data, src_data.as_ptr(), src_data.len()); 
    } 
} 
6

do wersji data:

use std::ptr; 
use std::fs; 
use std::io::{Write, SeekFrom, Seek}; 
use std::os::unix::prelude::AsRawFd; 
use mmap::{MemoryMap, MapOption}; 

// from crates.io 
extern crate mmap; 
extern crate libc; 

fn main() { 
    let size: usize = 1024*1024; 

    let mut f = fs::OpenOptions::new().read(true) 
             .write(true) 
             .create(true) 
             .open("test.mmap") 
             .unwrap(); 

    // Allocate space in the file first 
    f.seek(SeekFrom::Start(size as u64)).unwrap(); 
    f.write_all(&[0]).unwrap(); 
    f.seek(SeekFrom::Start(0)).unwrap(); 

    let mmap_opts = &[ 
     // Then make the mapping *public* so it is written back to the file 
     MapOption::MapNonStandardFlags(libc::consts::os::posix88::MAP_SHARED), 
     MapOption::MapReadable, 
     MapOption::MapWritable, 
     MapOption::MapFd(f.as_raw_fd()), 
    ]; 

    let mmap = MemoryMap::new(size, mmap_opts).unwrap(); 

    let data = mmap.data(); 

    if data.is_null() { 
     panic!("Could not access data from memory mapped file") 
    } 

    let src = "Hello!"; 
    let src_data = src.as_bytes(); 

    unsafe { 
     ptr::copy(src_data.as_ptr(), data, src_data.len()); 
    } 
} 
+0

Pojawia się błąd [E0433]: nie udało się rozwiązać. Nie można znaleźć "consts" w "libc" próbując skompilować. Naprawiono zmianę 'libc :: consts :: os :: posix88 :: MAP_SHARED' na' libc :: MAP_SHARED'. –