使用mmap将文件映射到虚拟地址空间进行操作

简介: 使用mmap将文件映射到虚拟地址空间进行操作

文章目录

使用mmap将文件映射到进程的虚拟地址空间,对内存的操作,直接反应到文件中。

相关概念:

代码参考:

执行验证

代码获取文件的元数据

文件的元数据

相关使用函数

代码实现

执行


使用mmap将文件映射到进程的虚拟地址空间,对内存的操作,直接反应到文件中。

相关概念:

Linux od命令用于输出文件内容。


  • od指令会读取所给予的文件的内容,并将其内容以八进制字码呈现出来。

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);


  • 头文件需要包含<sys/mman.h>
  • 功能:映射文件或设备到内存空间
  • 参数:
  • addr:映射后的虚拟地址空间的地址(一般为NULL)

  • length:映射的长度

  • prot:

  • PROT_NONE Pages may not be accessed.
  • PROT_EXEC Pages may be executed.
  • PROT_READ Pages may be read.
  • PROT_WRITE Pages may be written.
  • flags:


  • MAP_SHARED:
  • MAP_PRIVATE:
  • MAP_ANONYMOUS: 不支持文件映射
  • fd:-1

  • offset:0

  • 返回值:
  • MAP_FAILED 错误 errno被设置
  • 成功返回映射区域的地址

int munmap(void *addr, size_t length);

  • 功能:解除内存映射
  • 参数:
  • addr:是mmap(2)的返回值
  • length:同mmap(2)函数中的length
  • 返回值:
  • 0 成功
  • -1 失败 errno被设置

代码参考:

#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[]){
  int fd;
  //以读写方式打开文件
  fd=open(argv[1],O_RDWR);
  if(fd==-1){
  perror("open");
  return 1;
  }
  //建立映射
  void *p=mmap(NULL,6,\
  PROT_READ|PROT_WRITE,
  MAP_SHARED,fd,0);
  if(p==MAP_FAILED){
  perror("mmap");
  return 2;
  }
  printf("success...\n");
  //关闭文件
  close(fd);
  //对内存的操作
  int *q=(int *)p;
  q[0]=0x30313233;
  //解除映射
  munmap(p,6);
  return 0;
}


执行验证

20200204094016464.png

代码获取文件的元数据

文件的元数据

文件的元数据就是文件的属性,使用

ls -l [文件名]#查看

20200204094651879.png

相关使用函数

  • 如何获取一个文件的元数据?

使用系统调用stat(2)获取文件的元数据。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:获取文件的状态信息
参数:
path:指定了文件的名字
buf:将文件的状态信息存储到buf指定的空间里。
返回值:
-1  错误   errno被设置
0  成功
struct stat{
  dev_t   st_dev;  /* ID of device containing file */
        ino_t   st_ino;     /* inode number */
        mode_t  st_mode;    /* protection */
        nlink_t st_nlink;   /* number of hard links */
        uid_t   st_uid;     /* user ID of owner */
        gid_t   st_gid;     /* group ID of owner */
        dev_t   st_rdev;    /* device ID (if special file) */
        off_t   st_size;    /* total size, in bytes */
  blksize_t st_blksize; /* blocksize for file system I/O */
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
};


  • 如何将uid的数字转换为用户的名字?
getpwuid(3)
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能:获取用户的信息
参数:
uid:指定用户的uid
返回值:
返回一个指向struct passwd结构体的指针
NULL 找不到这个用户的信息或错误产生 如果是产生错误,errno被设置


/etc/passwd文件的内容

这个文件里存放的是系统的所有用户的信息。


struct passwd {
       char   *pw_name;       /* username */
       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 */
};


  • 如何通过gid获取组名?
getgrnam(3)
getgrgid(3)
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能:获取一条组信息
参数:
gid:指定的组id
返回值:
返回一个指向struct group结构体的指针
NULL 找不到这个组的信息或错误产生 如果是产生错误,errno被设置.


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


  • 组信息存放在/etc/group文件中
  • 20200204095113628.png
  • 将长整型的时间转换为字符串格式的时间


ctime(3)
#include <time.h>
char *ctime(const time_t *timep);
功能:将长整型的时间转换为字符串格式
参数:
timep:长整型的时间
返回值:
NULL   错误
字符串


代码实现

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int main(int argc,char *argv[]){
  struct stat sbuf;
  struct passwd *p;
  int s; 
  //获取指定文件的元数据
  s=stat(argv[1],&sbuf);
  if(s==-1){//获取文件的元数据失败
  perror("stat");
  return 1;
  }
  printf("size:%ld\n",sbuf.st_size);
  printf("hard links:%d\n",\
  sbuf.st_nlink);  
  printf("inode number:%lu\n",\
  sbuf.st_ino);
  //printf("uid:%d\n",sbuf.st_uid);
  p=getpwuid(sbuf.st_uid);
  if(p==NULL){
  return 2;
  }
  printf("username:%s\n",p->pw_name);
  //printf("gid:%d\n",sbuf.st_gid);
  struct group *q=\
  getgrgid(sbuf.st_gid);
  printf("group name:%s\n",q->gr_name);
  char *st=ctime(&sbuf.st_atime);
  printf("time:%s\n",st);
  printf("mode:%o\n",sbuf.st_mode);
#if 0
  if(S_ISREG(sbuf.st_mode))printf("-");
  if(S_ISDIR(sbuf.st_mode))printf("d");
  printf("\n");
#endif
  switch(sbuf.st_mode&S_IFMT){
  case S_IFREG:
    printf("-");
    break;
  case S_IFDIR:
    printf("d");
    break;
  default:
    break;
  }
  printf("\n");
  //打印出属主的权限
  if(sbuf.st_mode&S_IRUSR)
  printf("r");
  else 
  printf("-");
  if(sbuf.st_mode&S_IWUSR)
  printf("w");
  else
  printf("-");
  printf("\n");
#if 0
  switch(sbuf.st_mode&00700){
  case S_IRUSR:
    printf("r");
    break;
  case S_IWUSR:
    printf("w");
    break;
  case S_IXUSR:
    printf("x");
    break;
  default:
    break;
  }
#endif
  return 0;
}


执行

20200204095315253.png

相关文章
|
9月前
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
11月前
|
前端开发
使用 async/await 结合 try/catch 处理 Promise.reject()抛出的错误时,有什么需要注意的地方?
使用 async/await 结合 try/catch 处理 Promise.reject()抛出的错误时,有什么需要注意的地方?
441 57
|
Linux iOS开发 MacOS
安装Python 在 Windows、macOS 和 Linux上的详细步骤
安装Python 在 Windows、macOS 和 Linux上的详细步骤
599 2
|
编解码 前端开发 开发者
探索无界:前端开发中的响应式设计深度实践与思考###
本文将带你领略响应式设计的精髓,一种超越传统页面布局限制的设计策略,它要求开发者以灵活多变的思维,打造能够无缝适应各种设备与屏幕尺寸的Web体验。通过深入浅出的讲解、实际案例分析以及技术实现细节的探讨,本文目的是激发读者对于响应式设计深层次的理解与兴趣,鼓励在实际应用中不断创新与优化。 ###
425 10
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
2347 1
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
525 0
Linux C/C++之IO多路复用(poll,epoll)
|
SQL XML Java
Mybatis的原理和MybaitsPlus
这篇文章对比分析了Mybatis和Mybatis Plus的特点与底层实现机制,探讨了两者之间的差异及各自的优势。
410 0
|
存储 机器学习/深度学习 芯片
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
|
Ubuntu Linux Docker
Win11彻底卸载WSL2系统(去除导航窗格Linux图标)
Win11彻底卸载WSL2系统(去除导航窗格Linux图标)
16475 50