Linux 操作二:文件映射与文件状态

Linux 操作二:文件映射与文件状态查询

文件映射

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写数据到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。

在这里插入图片描述

mmap函数:

  • 头文件

    #include <sys/mman.h> 
    
  • 函数原型

    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    //解除映射
    int munmap(void *addr, size_t length);
    
  • 参数说明

    • addr:映射的地址空间首地址,NULL 表示让系统决定;

    • length:地址空间大小

    • prot:映射的地址空间访问方式,必须和文件打开方式匹配

    • flags: 映射的地址空间的访问标记常见的标志位:

      1. MAP_SHARED
        这个选项表示映射的内存区域与文件共享,即对映射内存区域的修改会直接反映到原始文件中。通常用于多个进程共享同一文件的情况。
        • 例如:进程 A 和进程 B 都映射了同一个文件,进程 A 修改了映射区域中的内容,进程 B 可以立即看到这些修改。
      2. MAP_PRIVATE
        这个选项表示映射的内存区域与文件私有,修改映射区域的内容不会写回到原文件。此类修改仅在当前进程的内存中有效,其他进程不可见。
        • 例如:进程 A 映射了一个文件并修改了映射区域的内容,但文件本身保持不变。
      3. MAP_ANONYMOUS
        这个选项表示创建一个匿名内存映射,即该映射不与任何文件相关联。fd 参数通常为 -1。它用于分配一块内存,而不是映射一个文件。对于不需要读取或写入文件的场景,匿名映射特别有用。
        • 例如:创建一个内存区域供程序使用(如内存池、数据结构等),而不需要任何文件作为后端。
      4. MAP_FIXED
        这个选项表示指定的 addr 地址是映射区域的起始地址。它要求映射区域严格地在该地址上开始。如果该地址已有其他映射或冲突,则会直接替换现有的映射区域。
        • 注意:如果指定的地址无法映射(例如,无法与当前地址空间兼容),mmap 将返回 MAP_FAILED
      5. MAP_FILE
        这个选项指定映射的是文件,通常默认情况下,mmap 会将文件映射到内存。该选项几乎与 MAP_SHARED 等价,但出于兼容性考虑,MAP_FILE 仍然可以使用。
      6. MAP_HUGETLB
        这个选项表示使用大页面(huge pages)。它要求映射使用大页内存,而不是系统默认的标准页面。这个选项通常需要超级用户权限,并且在支持大页的操作系统中才有效。
        • 例如:在内存密集型应用(如数据库、虚拟机管理程序)中,使用大页面可以提高内存管理的效率。
      7. MAP_LOCKED
        这个选项表示映射的内存区域在物理内存中将被锁定,操作系统不会将其交换到交换空间(swap)中。这对于实时应用或对内存访问有严格要求的应用非常有用。
      8. MAP_NORESERVE
        这个选项表示在创建映射时不保留交换空间(swap),即使映射的内存区域并没有实际分配内存。这通常用于创建一个大区域的虚拟内存映射,期望它不会被使用。
        • 该选项一般在大数据结构的内存分配中使用,以避免过多的交换空间消耗。
      9. MAP_POPULATE
        这个选项会在映射时立即预取(prefetch)所有的页面,即使这些页面还没有被访问过。它可以减少后续对内存的访问延迟,适用于希望提前加载数据的应用。
      10. MAP_STACK
        这个选项用来为程序的线程栈创建映射,表示该映射是为了线程的栈而创建的。通常由系统自动处理。
    • fd: 需映射的文件描述符

    • offset: 文件存储空间的偏移量

  • 返回值

    • 成功:munmap返回 0 ,mmap 返回映射后的地址;
    • 出错:返回 MMAP_FAILED,并将错误码存入 errno 中
  • 案例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    int main() {
        const char *filename = "testfile.txt";
        int fd = open(filename, O_RDWR);  // 打开文件,读取/写入权限
        if (fd == -1) {
            perror("open");
            return 1;
        }
    
        // 获取文件的大小
        off_t file_size = lseek(fd, 0, SEEK_END);
        
        // 使用 mmap 映射文件到内存
        char *mapped = (char *)mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if (mapped == MAP_FAILED) {
            perror("mmap");
            close(fd);
            return 1;
        }
    
        // 修改文件内容
        mapped[0] = 'H';  // 将文件的第一个字符改为 'H'
    
        // 同步映射区的内容到文件
        if (msync(mapped, file_size, MS_SYNC) == -1) {
            perror("msync");
        }
    
        // 解除映射
        if (munmap(mapped, file_size) == -1) {
            perror("munmap");
        }
    
        close(fd);
        return 0;
    }
    
  • 文件映射与系统i/o的区别

    • 抽象层次

      • 文件映射(Memory-Mapped Files):文件映射是一种将文件内容映射到进程的虚拟内存中的技术。通过文件映射,程序可以像访问内存一样访问文件的内容,而不需要显式地进行文件读取或写入操作。文件映射通过操作系统的虚拟内存管理机制来管理文件的加载和访问。

      • 系统I/O(System I/O):系统I/O是通过操作系统提供的系统调用(如 read, write, open, close 等)直接进行文件操作。程序需要显式地读取或写入数据到文件中,通常依赖于内存缓冲区。

    • 性能和效率

      • 文件映射:文件映射能够提供更高效的文件操作,尤其是在处理大文件或频繁访问文件的场景下。操作系统会自动将文件的数据加载到内存中,并根据需要进行页面交换。文件映射的优势在于它通过内存管理机制减少了多次I/O操作,提高了性能。内存映射文件可以直接在内存中访问,从而避免了频繁的磁盘I/O。

      • 系统I/O:系统I/O操作通常需要显式地读取或写入文件,每次操作都可能涉及磁盘I/O,尤其是在没有有效缓存时。系统I/O的性能受到磁盘I/O和缓冲策略的影响,通常比文件映射较慢,特别是在频繁读取大文件时。

    • 访问方式

      • 文件映射:文件映射将文件的一部分或整个文件映射到进程的虚拟地址空间,使程序可以通过指针直接访问文件内容。这种访问方式类似于访问普通内存,程序员可以像操作内存一样对文件进行读写。

      • 系统I/O:系统I/O需要使用操作系统提供的接口(如 read, write 等)来显式地读取或写入文件内容,数据需要先从文件中读取到内存中的缓冲区,然后进行处理。文件的访问方式是通过系统调用来完成的。

    • 数据同步

      • 文件映射:文件映射的更大优点之一是,操作系统负责管理数据的同步。数据可以在内存中直接操作,操作系统会定期将内存中更改的数据写回磁盘。为了保证数据一致性,通常会使用 msyncmunmap 等函数来手动同步数据。

      • 系统I/O:系统I/O通常依赖于缓冲区来处理数据,程序员需要显式地调用 flush 等函数来确保缓冲区的内容被写回磁盘,或者使用文件关闭操作来触发数据的同步。

    • 内存使用

      • 文件映射:文件映射会直接将文件的一部分或整个文件映射到进程的虚拟内存空间。操作系统会为映射区域分配虚拟内存,并在实际访问时将数据从磁盘加载到内存中。对于大型文件,文件映射只会在需要时加载文件的部分数据,而不是将整个文件加载到内存中。

      • 系统I/O:系统I/O操作通常需要将文件的数据读入到应用程序提供的缓冲区中。缓冲区的大小由程序员控制,且每次I/O操作都可能导致较高的内存使用,尤其是在读取大型文件时。

总结:
  • 文件映射:通过将文件映射到内存中,提供了一种高效的方式来处理文件,可以像操作内存一样访问文件内容,适用于需要频繁或大规模访问文件的场景。
  • 系统I/O:是传统的文件操作方式,需要显式进行文件读取或写入操作,适用于一般的文件访问,但性能和灵活性相对较低。

文件状态查询

  • 头文件

    #include <fcntl.h>            
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
  • 函数原型:

    int stat(const char *path, struct stat* buf)
    int fstat(int fd, struct stat *buf);
    
  • 参数说明

    • path:要操作的文件名或路径;

    • buf:指向stat 结构体的指针,用来获取文件状态信息:

      struct stat 
      {
          dev_t          st_dev;            //文件设备编号
          ino_t          st_ino;            //文件inode节点号
          mode_t      st_mode;              //文件类型,访问权限等
          nlink_t       st_nlink;           //文件的连接数
          uid_t          st_uid;            //文件所有者的用户ID
          gid_t          st_gid;            //文件所有者对应的组ID
          dev_t         st_rdev;            //若文件为设备文件,则表示设备编号
          off_t          st_size;           //文件大小,对应的文件字节数
          blksize_t    st_blksize;          //文件系统的 I/O 缓冲区大小
          blkcnt_t     st_blocks;           //占用文件区块数量,每一区块512 字节
          time_t        st_atime;           //文件最后一次被访问的时间
          time_t        st_mtime;           //文件内容最后一次被修改的时间
          time_t        st_ctime;           //最后一次改变时间(属性改变)
      };
      
    • fd:文件描述符

    • st_mode

      st_mode 常见取值: (八进制,文件类型主要取决第3字节)

      S_IFSOCK0140000socket 套接字文件
      S_IFLNK0120000链接文件
      S_IFREG0100000一般文件
      S_IFBLK0060000块设备文件
      S_IFDIR0040000目录
      S_IFCHR0020000字符设备文件
      S_IFIFO0010000管道文件

      上述的文件类型在POSIX中定义了检查这些类型的宏定义:

      S_ISLNK (st_mode)判断是否为链接文件
      S_ISREG (st_mode)是否为一般文件
      S_ISDIR (st_mode)是否为目录
      S_ISCHR (st_mode)是否为字符设备文件
      S_ISBLK (st_mode)是否为块设备文件
      S_ISSOCK (st_mode)是否为socket套接字文件
      S_ISFIFO (st_mode)是否为管道文件

      st_mode 其他常见取值:

      S_IRWXU00700自己拥有所有权限
      S_IRUSR00400自己拥有读权限
      S_IWUSR00200自己拥有写权限
      S_IXUSR00100自己拥有执行权限
      S_IRWXG00070自己组拥有所有权限
      S_IRGRP00040自己组拥有写权限
      S_IWGRP00020自己组拥有执行权限
      S_IXGRP00010自己组拥有执行权限
      S_IRWXO00007其他组用户拥有所有权限
      S_IROTH00004其他组用户拥有读权限
      S_IWOTH00002其他组用户拥有写权限
      S_IXOTH00001其他组用户拥有执行权限

利用用户ID获取用户信息,

  • 头文件

    #include <sys/types.h>   
    #include <pwd.h>
    
  • 函数原型

    struct passwd* getpwuid(uid_t uid);
    
  • 参数说明

    uid:用户id;

利用用户组ID获取用户组信息

  • 头文件

    #include <sys/types.h>  
    #include <grp.h>
    
  • 函数原型

    struct group *getgrgid(gid_t gid)
    
  • 参数说明

    gid:用户组id;

  • 返回值

    成功后返回下列结构体:

struct passwd {
               char*   pw_name;                  /* user name */
               char*   pw_passwd;                /* user password */
               uid_t    pw_uid;                  /* user ID */
               gid_t    pw_gid;                  /* group ID */
               char*  pw_gecos;                  /* user information */
               char*  pw_dir;                    /* home directory */
               char*  pw_shell;                  /* shell program */

           };

struct group {
               char*   gr_name;                  /* group name */
               char*   gr_passwd;                /* group password */
               gid_t     gr_gid;                 /* group ID */
               char** gr_mem;                    /* group members */
         };
  • 案例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <grp.h>
    #include <sys/types.h>
    
    int main() {
        gid_t gid = 1000;  // 替换为一个有效的组 ID
        struct group *grp = getgrgid(gid);
    
        if (grp != NULL) {
            printf("组名: %s\n", grp->gr_name);
            printf("组 ID: %d\n", grp->gr_gid);
            printf("组成员: ");
            for (char **member = grp->gr_mem; *member != NULL; member++) {
                printf("%s ", *member);
            }
            printf("\n");
        } else {
            perror("getgrgid");
        }
     	struct passwd *pw = getpwuid(uid);
        if (pw != NULL) {
            printf("用户名: %s\n", pw->pw_name);
            printf("用户 ID: %d\n", pw->pw_uid);
            printf("主组 ID: %d\n", pw->pw_gid);
            printf("主目录: %s\n", pw->pw_dir);
            printf("登录 Shell: %s\n", pw->pw_shell);
        } else {
            perror("getpwnam");
        }
        return 0;
    }
    
    
    
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955953.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络编程-TCP套接字

文章目录 初始TCP套接字TCP的Socket APISocketServerSocket 使用TCP模拟通信服务器端客户端 上述测试代码的问题分析IO的输入缓冲区的问题关于TCP协议中的粘包的问题不能进行多线程通信的问题 处理问题之后的完整代码启动多个实例完整代码测试结果 关于IO多路复用机制的引入 初…

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈 开发背景 可能大家听过过蓝湖可以转ui设计图为vue.js&#xff0c;react native代码&#xff0c;那么请问听说过将figma的设计图转换为flutter源代码吗?本文优雅草央千澈带…

重拾Python学习,先从把python删除开始。。。

自己折腾就是不行啊&#xff0c;屡战屡败&#xff0c;最近终于找到前辈教我 第一步 删除Python 先把前阵子折腾的WSL和VScode删掉。还是得用spyder&#xff0c;跟matlab最像&#xff0c;也最容易入手。 从VScode上搞python&#xff0c;最后安装到appdata上&#xff0c;安装插…

【机器学习实战中阶】音乐流派分类-自动化分类不同音乐风格

音乐流派分类 – 自动化分类不同音乐风格 在本教程中,我们将开发一个深度学习项目,用于自动化地从音频文件中分类不同的音乐流派。我们将使用音频文件的频率域和时间域低级特征来分类这些音频文件。 对于这个项目,我们需要一个具有相似大小和相似频率范围的音频曲目数据集…

[Qt]事件-鼠标事件、键盘事件、定时器事件、窗口改变事件、事件分发器与事件过滤器

目录 前言&#xff1a;Qt与操作系统的关系 一、Qt事件 1.事件介绍 2.事件的表现形式 常见的Qt事件&#xff1a; 常见的事件描述: 3.事件的处理方式 处理鼠标进入和离开事件案例 控件添加到对象树底层原理 二、鼠标事件 1.鼠标按下和释放事件&#xff08;单击&#x…

后盾人JS -- 好用的 JavaScript Symbol 类型

Symbol使用场景介绍 举个例子&#xff0c;当leader让你去机房取某个电脑的时候&#xff0c;机房那么多电脑&#xff0c;你怎么知道取哪个 所以这个时候symbol的作用就显现出来了&#xff08;上面有什么贴纸的&#xff0c;什么型号的电脑&#xff09; 声明定义Symbol的几种方…

社区版Dify实现文生视频 LLM+ComfyUI+混元视频

社区版Dify实现文生视频 LLMComfyUI混元视频 一、 社区版Dify实现私有化混元视频效果二、为什么社区版Dify可以在对话框实现文生视频&#xff1f;LLMComfyUI混元视频 实现流程图&#xff08;重点&#xff09;1. 文生视频模型支持ComfyUI2. ComfyUI可以轻松导出API实现封装3. Di…

数智化转型 | 星环科技Defensor 助力某银行数据分类分级

在数据驱动的金融时代&#xff0c;数据安全和隐私保护的重要性日益凸显。某银行作为数字化转型的先行者&#xff0c;面临着一项艰巨的任务&#xff1a;如何高效、准确地对分布在多个业务系统、业务库与数仓数湖中的约80万个字段进行数据分类和分级。该银行借助星环科技数据安全…

Spring boot启动原理及相关组件

优质博文&#xff1a;IT-BLOG-CN 一、Spring Boot应用启动 一个Spring Boot应用的启动通常如下&#xff1a; SpringBootApplication Slf4j public class ApplicationMain {public static void main(String[] args) {ConfigurableApplicationContext ctx SpringApplication.…

中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)

我开发了一个用于自动评教的工具&#xff0c;大家可以试着用用&#xff0c;下面是链接。 https://github.com/restrain11/auto_teachingEvaluate 可以点个星吗&#xff0c;感谢&#xff01;&#x1fae1; 以下是我在开发过程中学到的知识 以及 碰到的部分问题 目录 动态爬虫和静…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包&#xff0c;主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等&#xff0c;内容很多。我们基础学习的时候&#xff0c;只有关注张量的创建、序列化&#xff0c;随机数、张量的数学数学计算等常…

机器学习-距离的度量方法

文章目录 一. 欧式距离二. 曼哈顿距离三. 切比雪夫距离四. 闵式距离1. p不同取值,表示不同距离2. 当 ( p → ∞ ) ( p \to \infty ) (p→∞) 时&#xff0c;为什么闵式距离变为切比雪夫距离 五. 总结 一. 欧式距离 欧式距离&#xff08;Euclidean distance&#xff09;:多维空…

ComfyUI 矩阵测试指南:用三种方法,速优项目效果

在ComfyUI中&#xff0c;矩阵测试也叫xyz图表测试&#xff0c;作用是通过控制变量的方式来对Lora模型以及各种参数开展测试&#xff0c;并进行有效区分。其中测试方法有很多种&#xff0c;可以通过借助插件也可以自行搭建工作流实现&#xff0c;下面介绍3种方式&#xff1a; 1…

内存与缓存:保姆级图文详解

文章目录 前言1、计算机存储设备1.1、硬盘、内存、缓存1.2、金字塔结构1.3、数据流通过程 2、数据结构内存效率3、数据结构缓存效率 前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0c;您的关注是我持续创作的…

UllnnovationHub,一个开源的WPF控件库

目录 UllnnovationHub1.项目概述2.开发环境3.使用方法4.项目简介1.WPF原生控件1.Button2.GroupBox3.TabControl4.RadioButton5.SwitchButton6.TextBox7.PasswordBox8.CheckBox9.DateTimePicker10.Expander11.Card12.ListBox13.Treeview14.Combox15.Separator16.ListView17.Data…

【STM32-学习笔记-10-】BKP备份寄存器+时间戳

文章目录 BKP备份寄存器Ⅰ、BKP简介1. BKP的基本功能2. BKP的存储容量3. BKP的访问和操作4. BKP的应用场景5. BKP的控制寄存器 Ⅱ、BKP基本结构Ⅲ、BKP函数Ⅳ、BKP使用示例 时间戳一、Unix时间戳二、时间戳的转换&#xff08;time.h函数介绍&#xff09;Ⅰ、time()Ⅱ、mktime()…

Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批

文章目录 引言I 表结构主要表前缀及其用途核心表II 流程设计器(Flowable BPMN模型编辑器插件)Flowable-UIvue插件III 流程部署部署步骤例子:根据流程模型ID部署IV 启动流程启动步骤ACT_RE_PROCDEF:流程定义相关信息例子:根据流程 ID 启动流程V 流程审批审批步骤Flowable 审…

java根据模板导出word,并在word中插入echarts相关统计图片以及表格

引入依赖创建word模板创建ftl模板文件保存的ftl可能会出现占位符分割的问题&#xff0c;需要处理将ftl文件中的图片的Base64删除&#xff0c;并使用占位符代替插入表格&#xff0c;并指定表格的位置在图片下方 Echarts转图片根据模板生成word文档DocUtil导出word文档 生成的wor…

晨辉面试抽签和评分管理系统之十:如何搭建自己的数据库服务器,使用本软件的网络版

晨辉面试抽签和评分管理系统&#xff08;下载地址:www.chenhuisoft.cn&#xff09;是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…

Asp .Net Core 实现微服务:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现

什么是 Ocelot ? Ocelot是一个开源的ASP.NET Core微服务网关&#xff0c;它提供了API网关所需的所有功能&#xff0c;如路由、认证、限流、监控等。 Ocelot是一个简单、灵活且功能强大的API网关&#xff0c;它可以与现有的服务集成&#xff0c;并帮助您保护、监控和扩展您的…