当文件句柄超出其作用域时,它是如何关闭的?

6

我不明白当Rust处理文件句柄超出作用域时会发生什么。例如,我创建一个文件并写入几个单词:

let wd = os::getcwd().unwrap_or(Path::new("/"));
let mut file = File::create(&Path::new("daemon_log.txt"));
file.write_all(format!("DAEMON CWD: {}", wd.as_str().unwrap_or("some problems")).as_bytes());

在文件超出范围的地方,编译器应该插入释放内存的指令。如果我对阻塞IO通常的实现方式的理解是正确的,那么除了释放内存之外,进程还应该释放一些锁。
我担心的是,在File的源代码中,我找不到任何提示让编译器这样做。这篇旧文章说所有魔法都在为File实现Drop特征,但现在似乎不是这样,因为我在std::ops.rsstd::old_io::fs.rs中都找不到Drop特征的实现。 更新 我再次检查了 Filewrite_all 实现,并发现 write 方法使用了一些描述符(FileDesc)。我在文档中没有找到任何相关信息,于是去 GitHub 上找到了 this。它看起来是我问题的答案,但我被评论中的一行困惑了:

// closing stdio file handles makes no sense, so never do it

这是什么意思?我永远不应该自己调用 libc::close 吗?还是他们自己也不确定应该如何实现?
2个回答

8

对于POSIX平台,File在模块sys::fs2中定义为struct File(FileDesc),其中FileDesc是文件描述符号的封装。 FileDesc的析构函数关闭了文件:

impl Drop for FileDesc {
    fn drop(&mut self) {
        // closing stdio file handles makes no sense, so never do it. Also, note
        // that errors are ignored when closing a file descriptor. The reason
        // for this is that if an error occurs we don't actually know if the
        // file descriptor was closed or not, and if we retried (for something
        // like EINTR), we might close another valid file descriptor (opened
        // after we closed ours.
        if self.fd > libc::STDERR_FILENO {
            let _ = unsafe { libc::close(self.fd) };
        }
    }
}

Windows平台的实现将File定义为Handle值的包装器,其析构函数调用CloseHandle()


这似乎是一个有效的答案。谢谢 :) - mkrakhin

0

抱歉,我不明白它与文件有什么关系。但是它让我再次检查了Writer的实现。我更新了一个问题。 - mkrakhin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接