【Linux编程】存储映射I/O

【Linux编程】存储映射I/O

大家好,又见面了,我是全栈君。

存储映射I/O使一个磁盘文件与存储空间中的一个缓冲区相映射,对缓冲区的读、写操作就是对文件的读、写操作,从而能够不再使用read、write系统调用。


将文件映射到存储区的函数由mmap完毕,函数原型例如以下:
#include <sys/mman.h>
 
/* 成功返回映射区起始地址,出错返回MAP_FAILED */
void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);

參数说明:
  • addr:指定映射存储区的起始地址,通常为0表示由系统选择起始地址。
  • len:须要映射的字节数。
  • prot:对映射存储区的保护要求,不能超过open文件时的权限。
    • PROT_READ:映射区可读
    • PROT_WRITE:映射区可写
    • PROT_EXEC:映射区可运行
    • PROT_NONE:映射区不可訪问
  • flag:影响映射存储区的属性。
    • MAP_FIXED:返回值必须等于addr,不利于移植。不鼓舞使用。
    • MAP_SHARED:表示存储操作相当于对该文件的write。
    • MAP_PRIVATE:对映射区的存储操作导致创建该映射文件的一个私有副本。
  • filedes:指定要被映射的文件描写叙述符,映射之前须要先打开该文件。
  • off:要映射字节在文件里的起始偏移量。通常为0。

存储映射例如以下所看到的:
【Linux编程】存储映射I/O


測试代码:
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
 
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
 
int main(int argc, char *argv[])
{
    int fdin, fdout;
    void *src, *dst;
    struct stat statbuf;
 
    if (argc != 3)
    {
        printf("usage: %s <fromfile> <tofile>\n", argv[0]);
        return -1;
    }
 
    fdin = open(argv[1], O_RDONLY);
    fdout = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
 
    fstat(fdin, &statbuf);
 
    lseek(fdout, statbuf.st_size - 1, SEEK_SET);
    write(fdout, " ", 1);   /* lseek偏移量大于文件长度时。写操作将加长文件 */
 
    src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0);
    dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0);
 
    memcpy(dst, src, statbuf.st_size);  /* 数据复制 */
 
    munmap(src, statbuf.st_size);
    munmap(dst, statbuf.st_size);
 
    return 0;
}

此函数实现了文件内容之间的拷贝。

lseek + write的组合操作使得目标文件的大小添加到和源文件大小同样。由于当lseek设置的文件偏移量大于文件当前长度时。下一个写操作将会使文件增大。假设没有对目标文件扩大。那么进程会接收到SIGBUS信号。表示存储区中有地址无法映射到文件里。


mmap实际上是将包括文件内容的内核缓冲区映射到应用程序地址空间,然后用memcpy直接进行数据的拷贝。其优势在于避免了类似read、write系统调用,在内核空间和用户空间之间的数据传递。

參考:
《unix环境高级编程》 P390-P395.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116472.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月20日 下午9:00
下一篇 2022年1月20日 下午10:00


相关推荐

  • 迭代和递归的理解和区别

    迭代和递归的理解和区别最近做一些题经常会碰到迭代的方法解的,或者递归解法,容易搞混,特在此整理一下一.递归:由例子引出,先看看递归的经典案例都有哪些1.斐波那契数列斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……这个数列从第三项开始,每一项都等于前两项之和。2.阶乘n!=n*(n-1)*(n-2)*…*1(n>0)3.汉诺塔问…

    2022年5月3日
    38
  • Fiori介绍_fil简介

    Fiori介绍_fil简介为什么写这篇文章Fiori作为SAP最新以及将来的趋势平台,目前发展的非常快,作为一个FIORI技术的关注者,也一直想写点东西来介绍一下.前几天公司组织了一次Fiori的讲座,我作为主讲也参考SAP的介绍制作了一份PPT,在博客也分享出来,大家拿去用吧.SAP前端方案一句话:尽量简单,尽量根据个人的需求而定制.SAPFIORI简介FIORI是什么新的面孔面向所有用户跨平台FIORI应用

    2025年8月8日
    7
  • 【SpringBoot】39、SpringBoot上传文件至项目resources目录下

    【SpringBoot】39、SpringBoot上传文件至项目resources目录下当我们没有搭建单独的文件服务器时,我们需要将文件上传至项目目录下,今天我们就学习如何上传文件到项目的resources目录下一、引入依赖<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version></depende

    2022年6月13日
    32
  • 向量叉乘的右手螺旋定则

    向量叉乘的右手螺旋定则转自 https www cnblogs com FWFC p 9026082 htmlaXb 右手大拇指指向 a 正向 食指指向 b 正向 让中指与大拇指食指所在平面垂直 中指所指方向就是 aXb 的方向

    2026年3月20日
    2
  • Ajax beforeSend和complete 方法

    Ajax beforeSend和complete 方法

    2021年10月9日
    45
  • ArrayList扩容原理

    ArrayList扩容原理ArrayList扩容原理今天带来的下饭菜是ArrayList的扩容源码解读。相信大家对这盘菜都不陌生,我们经常使用它来定义一个集合,无论日常开发还是自己学习使用的频率是相当的高。而且大家也都一定知道ArrayList集合是通过数组实现的,但是在声明一组数据的时候都会选择ArrayList而不是数组,原因就是由于这组数据的元素的数量不确定,如果使用数组的话,我们还得亲自维护数组的长度,这时你一定会说TMD烦死了;但如果使用了ArrayList,维护数组长度的事情就不用我们操心了,我们只需要对这组数据进

    2022年6月3日
    33

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号