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;            //文件所有者的用户IDgid_t          st_gid;            //文件所有者对应的组IDdev_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;  // 替换为一个有效的组 IDstruct 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;
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读:CosAE Learnable Fourier Series for Image Restoration

这是 2024 NeurIPS 上发表的一篇文章&#xff0c;介绍了一种新型的基于傅里叶级数的通用编码器。 Abstract 本文介绍了余弦自动编码器&#xff08;Cosine Autoencoder, CosAE&#xff09;&#xff0c;这是一种新颖的通用自动编码器&#xff0c;它将经典傅里叶级数与前馈神经网…

数据库服务体系结构

1. 数据库服务应用配置 服务进行配置有什么作用&#xff1f; 实现服务运行启动 实现某些功能 应用配置有三种方式&#xff1f; 利用编译安装进行配置 编写配置文件信息 ,.默认的配置文件: /etc/my.cnf 利用启动命令参数配置信息&#xff0c;mysqld_safe --skip-grant-tables --…

Armv8/Armv9架构从入门到精通-介绍

CSDN学院课程连接&#xff1a;https://edu.csdn.net/course/detail/39573 1 讲师介绍 拥有 12 年手机安全、汽车安全、芯片安全开发经验&#xff0c;擅长 Trustzone/TEE/ 安全的设计与开发&#xff0c;对 ARM 架构的安全领域有着深入的研究和丰富的实践经验&#xff0c;能够…

【Web】2025西湖论剑·中国杭州网络安全安全技能大赛题解(全)

目录 Rank-l Rank-U sqli or not Rank-l username存在报错回显&#xff0c;发现可以打SSTI 本地起一个服务&#xff0c;折半查找fuzz黑名单&#xff0c;不断扔给fenjing去迭代改payload from flask import Flask, request, render_template_stringapp Flask(__name__)app…

2025.1.17——三、SQLi regexp正则表达式|

题目来源&#xff1a;buuctf [NCTF2019]SQLi1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;正常注入 step 2&#xff1a;弄清关键字黑名单 1.目录扫描 2.bp爆破 step 3&#xff1a;根据过滤名单构造payload step 4&#xff1a;regexp正则注…

使用 Java 开发 Android 应用:Kotlin 与 Java 的混合编程

使用 Java 开发 Android 应用&#xff1a;Kotlin 与 Java 的混合编程 在开发 Android 应用程序时&#xff0c;我们通常可以选择使用 Java 或 Kotlin 作为主要的编程语言。然而&#xff0c;有些开发者可能会想要在同一个项目中同时使用这两种语言&#xff0c;这就是所谓的混合编…

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

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

【C++】面试题整理(未完待续)

【C】面试题整理 文章目录 一、概述二、C基础2.1 - 指针在 32 位和 64 位系统中的长度2.2 - 数组和指针2.3 - 结构体对齐补齐2.4 - 头文件包含2.5 - 堆和栈的区别2.6 - 宏函数比较两个数值的大小2.7 - 冒泡排序2.8 - 菱形继承的内存布局2.9 - 继承重写2.10 - 如何禁止类在栈上分…

简历_使用 Redis 解决集群模式下的 Session 共享问题,使用拦截器实现用户的登录,校验和权限刷新以及对单位时间内请求频繁的用户IP地址进行限流。

系列博客目录 文章目录 系列博客目录1.使用 Redis 解决集群模式下的 Session 共享问题集群的session共享问题总结 2.使用拦截器实现用户的登录&#xff0c;校验和权限刷新3.对单位时间内请求频繁的用户IP地址进行限流。实现思路步骤&#xff1a;1. 添加 Redis 依赖2. 配置 Redi…

构建安全防线:基于视频AI的煤矿管理系统架构创新成果展示

前言 本文我将介绍一款AI产品的成果展示——“基于视频AI识别技术的煤矿安全生产管理系统”。这款产品是目前我在创业阶段和几位矿业大学的博士共同从架构设计、开发到交付的全过程中首次在博客频道发布, 我之前一直想写但没有机会来整理这套系统的架构, 因此我也特别感谢CSDN平…

浅谈计算机网络04 | 现代网络需求与技术支撑

现代网络需求与技术支撑 一、网络和因特网流量的类型剖析1.1 弹性流量的自适应特征1.2 非弹性流量的刚性特征1.3 实时流量特性 二、特定领域的网络需求解析2.1 大数据环境下的网络需求分析2.2 云计算环境下的网络需求分析2.3 移动数据环境下的网络需求分析 三、QoS和QoE&#x…

麒麟操作系统服务架构保姆级教程(十一)https配置

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 在运维工作中&#xff0c;加密和安全的作用是十分重要的&#xff0c;如果仅仅用http协议来对外展示我们的网站&#xff0c;过一段时间就会发现网站首页被人奇奇怪怪的篡改了&#xff0c;本来好好的博…

考研计算机组成原理——零基础学习的笔记

第一章 研究计算机硬件的学科。 1.计算机系统概述 计算机系统硬件软件&#xff08;系统软件&#xff1a;比如操作系统、数据库管理系统、标准程序库等&#xff0c;应用软件&#xff1a;QQ等&#xff09; 1.2计算机的层次结构 1.2.1计算机硬件的基本组成 冯诺伊曼计算机&a…

利用 LNMP 实现 WordPress 站点搭建

部署MySQL数据库 在主机192.168.138.139主机部署数据库服务 包安装数据库 apt-get install mysql-server 创建wordpress数据库和用户并授权 mysql> create database wordpress;#MySQL8.0要求指定插件 mysql> create user wordpress192.168.138.% identified with mys…

通过idea创建的springmvc工程需要的配置

在创建的spring mvc工程中&#xff0c;使用idea开发之前需要配置文件包括porm.xml、web.xml、springmvc.xml 1、porm.xml 工程以来的spring库&#xff0c;主要包括spring-aop、spring-web、spring-webmvc&#xff0c;示例配置如下&#xff1a; <project xmlns"http:/…

ASP.NET Core - 配置系统之自定义配置提供程序

ASP.NET Core - 配置系统之自定义配置提供程序 4. 自定义配置提供程序IConfigurationSourceIConfigurationProvider 4. 自定义配置提供程序 在 .NET Core 配置系统中封装一个配置提供程序关键在于提供相应的 IconfigurationSource 实现和 IConfigurationProvider 接口实现&…

gitlab runner正常连接 提示 作业挂起中,等待进入队列 解决办法

方案1 作业挂起中,等待进入队列 重启gitlab-runner gitlab-runner stop gitlab-runner start gitlab-runner run方案2 启动 gitlab-runner 服务 gitlab-runner start成功启动如下 [rootdocserver home]# gitlab-runner start Runtime platform …

python爬虫报错日记

python爬虫报错日记 类未定义 原因&#xff1a;代码检查没有问题**&#xff0c;位置错了**&#xff0c;测试代码包含在类里…… UnicodedecodeError错误 原因&#xff1a;字符没有自动转换成utf-8格式 KeyError&#xff1a;“href” 原因&#xff1a;前面运行正常&#x…

简历_基于 Cache Aside 模式解决数据库与缓存一致性问题。

系列博客目录 文章目录 系列博客目录缓存更新策略总结案例&#xff1a;给查询商铺的缓存添加超时剔除和主动更新的策略 说到解决数据库与缓存一致性的问题&#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…