使用mmap(linux系统调用)追加文件内容

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用mmap(linux系统调用)追加文件内容相关的知识,希望对你有一定的参考价值。

在网上找了一些例子,都实践了一遍,但是这些例子都是读取文件,或者将文件中的字符串“asdf”改为“qwer”这种,我想要的功能是在文件末尾增加一行新的内容,就是普通的write进去,求方法。我自己根据mmap文档中的参数说明,尝试了若干次都失败了。
源码如上图,创建一个文件“mmapfile.txt”,往里面追加一句话“just a test for mmap.”
下一次再执行这个程序,mmapfile.txt文件中之前的内容不被删除,而是”追加“。

mmap 是做内存映射,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。
void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t
offset);
PROT_WRITE //页可以被写入 //这个参数你设置没有?追问

源码如上图

参考技术A 如果你想体验Linux系统,我觉得最好的办法是安装了Linux操作系统,再好的园林绿化,仿真工具不能让你真正体验到了Linux的真正威力。一般可以安装Vista系统的配置非常高,可以安装虚拟机软件的Windows平台,虚拟机内安装了Linux系统。在这种情况下,有一个完整的Linux系统(带独立的桌面环境,文件系统,内存空间等,和一台电脑没有区别),而要像在Windows下运行的Windows应用程序,不会将您的Windows产生任何危害。
常见的虚拟机软件Vmware的,现在最新的版本是6.0,很不错,推荐,以及微软的VirtualPC,功能也很不错,但我还没有用完。
参考技术B 图代码用了lseek(reposition read/write file offset),这个并不能改变文件的大小,所以追加失败。 参考技术C 最简单的办法是:
echo "文件内容“ >> 文件追问

我必须用mmap这个方法

追答

网上查mmap是用来内存映射的?你确定用这个来修改文件?

追问

确定,开源项目log4c中就使用了这个方法,在linux系统中运行速度比普通的fprintf, write这类c语言流输入速度快很多。我自己懂得fprintf这种入门级的c语言方法

追答

好吧,那还是等高手来解答吧,这个不懂

Linux 内核 内存管理内存管理系统调用 ⑤ ( 代码示例 | 多进程共享 mmap 内存映射示例 )

文章目录





一、进程一描述



在上一篇博客 【Linux 内核 内存管理】内存管理系统调用 ④ ( 代码示例 | mmap 创建内存映射 | munmap 删除内存映射 ) 中 , 完成了 进程一 的程序 ,

在该进程中 , 创建并打开文件 , 为该文件设置大小 ,

使用 mmap 创建 " 文件映射 " , 并通过直接访问内存的方式 , 为该文件设置数据 ;

数据设置完毕后 , 休眠 8 8 8 秒 , 在这段休眠的时间段 , 运行 进程二 , 在 进程二中 , 创建相同文件的 mmap " 文件映射 " , 读取在 进程一 中写入的文件内容 ;





二、进程二描述



进程二 的源码 , 与上一篇博客 【Linux 内核 内存管理】内存管理系统调用 ④ ( 代码示例 | mmap 创建内存映射 | munmap 删除内存映射 ) 中 进程一 源码类似 , 只是将写入 mmap 文件映射 数据 , 修改为 读取 该 文件映射 数据 , 并打印出来 , 源码如下 :

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

#include <sys/mman.h>
#include <sys/types.h>


/*
    定义一个结构体 代表 " 学生 "
    结构体成员中设置一个 char* 字符串 和 int 类型数据
    分别代表 学生的 姓名 和 年龄
 */
typedef struct

    char name[4];  // 姓名
    int age;        // 年龄
student;


int main(int argc, char** argv)

    // 打开文件的 文件描述符
    int fd;

    // 循环控制变量
    int i;

    // 学生结构体指针 , 指向 student 结构体类型变量
    student* p_student;

    // 用于生成姓名字符串
    char name_char;

    // 打开文件
    fd = open(argv[1], O_CREAT | O_RDWR , 00777);

    // 创建文件映射
    // NULL : 映射区的开始地址
    // sizeof(student) * 1 : 文件映射区的长度
    // PROT_READ | PROT_WRITE : 内存保护的标志位 , 该内存页的内容可以 读取 写入 
    // MAP_SHARED : 指定映射关系 , 指的是该映射是进程的共享内存空间
    // fd : 文件描述符 , 被映射的文件 
    // 0 : 被映射文件的偏移量 , 从文件的哪个字节位置开始映射
    p_student = (student*)mmap(NULL, sizeof(student) * 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    // mmap 文件映射创建失败
    if (p_student == (void*) - 1)
    
        printf("mmap 文件映射创建失败 !");
        return -1;
    

    // 创建完文件映射之后 , 文件描述符就可以释放了
    close(fd);


    // 打印 10 个 student 结构体的数据内容
    for (i = 0; i < 10; i++)
    
        // 打印 student 结构体的 name 和 age 成员
        printf("name:%s , age:%d\\n", (*(p_student + i)).name, (*(p_student + i)).age);
    

    printf("第二进程 mmap 文件映射展示完毕 !\\n");
    return 0;

上述源码 , 放在 mmap_demo_02.c 文件中 , 执行

gcc mmap_demo_02.c -o mmap_demo_02

命令 , 编译该源码 , 编译出的可执行文件为 mmap_demo_02 ;





三、mmap 进程共享内存展示



先执行 进程一 mmap_demo_01 可执行程序 , 进程一 中通过 mmap 文件映射向文件中写出数据后 , 进入休眠阶段 ,

再执行进程二 mmap_demo_02 , 使用 mmap 文件映射访问 file 文件 , 此时打印出 进程一 中通过 mmap 文件映射写出的文件数据 ;

以上是关于使用mmap(linux系统调用)追加文件内容的主要内容,如果未能解决你的问题,请参考以下文章

Linux 内核 内存管理内存管理系统调用 ⑤ ( 代码示例 | 多进程共享 mmap 内存映射示例 )

linux mmap系统调用

Linux内存管理之mmap详解

Linux内存管理之mmap详解

Linux系统下不使用vivimtouch等方法来创建文件或追加内容

Linux中的mmap文件支持映射与匿名映射[关闭]