“fd not available for reading or writing” when mem

2019-08-09 04:44发布

问题:

I am trying to write data to a memory-mapped file in Rust but it won't memory map the specified file as it states the given fd is not available.

I can see it on the filesystem so it does exist with correct privileges. I suspect this is either a bug or I am not using the new IO API in the correct way.

mmap err = fd not available for reading or writing

Here's the code

use std::fs::File;
use std::os::MemoryMap;
use std::os::unix::prelude::AsRawFd;
use std::os::MapOption::{MapFd, MapWritable, MapReadable};

fn main() {
    let f = File::create("test.dat").unwrap();
    f.set_len(n as u64);

    let fd = f.as_raw_fd();

    let mmap = MemoryMap::new(n, &[MapReadable, MapWritable, MapFd(fd)]);

    match mmap {
        Ok(_) => println!("mmap success"),
        Err(ref err) => println!("mmap err = {}", err),
    }
}

回答1:

Files created with File::create are in write-only mode, but you are attempting to map the file for both reading and writing. Use OpenOptions to get a file with both modes:

#![feature(os, std_misc)]

use std::fs::OpenOptions;
use std::os::MemoryMap;
use std::os::unix::prelude::AsRawFd;
use std::os::MapOption::{MapFd, MapReadable, MapWritable};

fn main() {
    let n = 100;

    let f = OpenOptions::new()
        .read(true)
        .write(true)
        .truncate(true)
        .create(true)
        .open("test.dat")
        .unwrap();

    f.set_len(n as u64).unwrap();

    let fd = f.as_raw_fd();

    let mmap = MemoryMap::new(n, &[MapReadable, MapWritable, MapFd(fd)]);

    match mmap {
        Ok(_) => println!("mmap success"),
        Err(err) => println!("mmap err = {}", err),
    }
}

I figured this out by

  1. Grepping the code for "fd not available for reading or writing", which leads to this line, which aligns to ErrFdNotAvail (could also have changed mmap err = {} to mmap err = {:?}).

  2. Searching for that enum variant leads to this line, which maps the underlying libc::EACCES error.

  3. Checked out the man page for mmap to see what EACCES says:

The flag PROT_READ was specified as part of the prot argument and fd was not open for reading. The flags MAP_SHARED and PROT_WRITE were specified as part of the flags and prot argument and fd was not open for writing.



标签: rust