mmap, munmap - map or unmap files or devices into memory

mmap, munmap - map or unmap files or devices into memory

SYNOPSIS

 #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);

mmap() creates a new mapping in the virtual address space of the call‐
ing process. The starting address for the new mapping is specified in
addr. The length argument specifies the length of the mapping.
mmap() 创建一个虚拟地址空间的映射。
munmap()删除特定地址范围的映射。

addr : 映射地址,通常为NULL(由系统自动分配);
length : 映射空间大小
prot : 映射空间的权限(可执行、写、读或者无);
flag : 映射空间是否共享等;
fd : 文件描述符;
offset:文件偏移;

1st:通过linux系统调用函数对于文件的操作代码如下所示:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#define pathname "./text.txt"

int main(int argc, char** argv)
{
        int fd = open(pathname, O_RDWR);
        if (fd < 0)
        {
                perror("open");
                return 0;
        }
        char * st = (char *)malloc(5);
        fd = read(fd,st,5);       //读取text.txt前五个字符hello
        if (fd < 0)
        {
                perror("read");
                return 0;
        }
        printf("%s\n",st);
        close(fd);
        return 0;
}

xxx@ubuntu:~/CSDN/about_mmp$ gcc mmap.c
xxx@ubuntu:~/CSDN/about_mmp$ ls
a.out mmap.c text.txt
xxx@ubuntu:~/CSDN/about_mmp$ cat text.txt
hello about_mmaphello
xxx@ubuntu:~/CSDN/about_mmp$ ./a.out
hello

同样也可使用mmap映射一块内存对应于text.txt,可通过返回的指针直接对文件继续修改。
在使用mmap之前,mmap第二个参数length : 映射空间大小,即文件text.txt的大小可通过fstat函数获得,可通过man fstat查看函数说明如下:

NAME
       stat, fstat, lstat, fstatat - get file status

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *pathname, struct stat *buf);
       int fstat(int fd, struct stat *buf);
       int lstat(const char *pathname, struct stat *buf);
//These  functions return information about a file, in the buffer pointed to by buf.
//这些函数返回文件的信息,放于由buf指针指向的struct stat结构体中,结构体信息:
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 filesystem I/O */
               blkcnt_t  st_blocks;      /* number of 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

               struct timespec st_atim;  /* time of last access */
               struct timespec st_mtim;  /* time of last modification */
               struct timespec st_ctim;  /* time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

2nd:通过mmap函数映射出的空间对文件操作代码如下所示:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define pathname "./text.txt"
int main(int argc, char * argv[])
{
        int fd = open(pathname, O_RDWR);  //首先打开文件
        if (fd < 0)
        {
                perror("open_error");
                return 0;
        }

        struct stat stat_;       //定义一个struct stat结构体用于存放text.txt文件信息
        int ret = fstat(fd, &stat_);     //结构体stat_中的stat_.st_size项即为该文件的大小
        if (ret < 0)
        {
                perror("fstat_error");
                return 0;
        }
		//mmap函数映射的虚拟空间对应于text.txt文件的实际物理空间,也即通过修改映射出来的虚拟空间的地址,即可直接修改文件。
        char * ret_ = mmap(NULL, stat_.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if (ret_ == (void *)-1)
        {
                perror("mmao_error");
                return 0;
        }
        printf("ret_ = %s\n",ret_);
        ret[2] = '*';
        printf("ret_ = %s\n",ret_);
        munmap(ret_, stat_.st_size);     //删除映射
        return 0;

xxx@ubuntu:~/CSDN/about_mmp$ ./a.out
ret_ = hello about_mmaphello

ret_ = he*lo about_mmaphello

对比代码1和代码2,两种方式修改文件text.txt,代码1是通过系统调用函数进行修改,代码2是通过地址空间映射方式修改。LINUX下一切皆文件,当需要对某个文件中内容快速修改时,直接修改映射空间的当时明显要优于通过系统调用读写的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值