2015-02-14 30 views
11

Sto provando a creare un file mappato in memoria usando std::os::MemoryMap. L'approccio attuale si presenta come segue:Come creare e scrivere su file mappati in memoria?

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()); 
} 

Questo programma viene a mancare con

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

quando si chiama ptr::copy_memory o altre operazioni sui dati.

  • Qual è il motivo per cui non riesco a scrivere (o leggere) i dati da MemoryMap?
  • Qual è il modo corretto di utilizzare MemoryMap in ruggine?
+3

Che cosa si intende per "fallisce quando si chiama ..."? C'è un errore del compilatore, un crash in fase di esecuzione, qual è il messaggio di errore, ecc.? – delnan

+0

Vuoi che le modifiche vengano salvate nel file? – Shepmaster

+0

@delnan, aggiornato la domanda con il messaggio di errore – mkhq

risposta

10

Ti manca due parti principali:

  1. mmapdoesn't allocate any space on its own, quindi è necessario impostare un pò di spazio nel file. Senza questo, ottengo Illegal instruction: 4 durante l'esecuzione su OS X.

  2. MemoryMap è private by default quindi è necessario marcare la mappatura come pubblico in modo che le modifiche vengano riscritte nel file (sto assumendo si desidera che le scritture essere salvato). Senza questo, il codice viene eseguito, ma il file non viene mai modificato.

Ecco una versione che funziona per me:

#![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

versione aggiornata:

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

Viene visualizzato l'errore [E0433]: impossibile risolvere. Non è stato possibile trovare "consts" in "libc" che tentava di compilare. Corretto il cambiamento di 'libc :: consts :: os :: posix88 :: MAP_SHARED' in' libc :: MAP_SHARED'. –