mmap使用踩坑(读写文件)

下面是一个写文件并且在子进程中读取文件并输出的例子。
踩坑点:
1.open和mmap配合使用,如果是刚新create 的文件,文件大小为0.
需要通过write给增加文件大小,lseek可以通过移动seek指针配合write增加文件大小。
2.在mmap的时候一定要设置MAP_SHARED或者MAP_PRIVATE,否则的话会出错。

#include <cstdio>
#include <sys/mman.h>
#include <cstring>
#include <iostream>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
// 使用mmap读写文件

using namespace std;

int main() {

    int fd = open("./my_rw4.txt", O_CREAT | O_TRUNC|O_RDWR,0664);

    if(fd<0){
        perror("File not open");
        return 0;
    }
    struct stat state;
    // 获取文件的信息
    if(fstat(fd,&state)==-1){
        perror("fstat failed.");
        close(fd);
        return 0;
    }
    const char* ptr="This is the file.";

    lseek(fd,strlen(ptr)-1,SEEK_END);
    printf("The size of file: %d bytes.\n",state.st_size);
    write(fd,"",1);
    // if(ftruncate(fd,17456)==-1){
    //     perror("Error setting file size");
    //     close(fd);
    //     return 1;
    // }

    if(fstat(fd,&state)==-1){
        perror("fstat failed.");
        close(fd);
        return 0;
    }
    printf("The size of file: %d bytes.\n",state.st_size);


    char *addr = (char*)mmap(nullptr, strlen(ptr), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);
    if(addr==MAP_FAILED){
        perror("map failed.");
        close(fd);
        return 0;
    }

    // extern char* ptr="This is the file.";
    strcpy(addr,ptr);
    cout<<addr<<endl;
    if (msync(addr, strlen(ptr), MS_SYNC) == -1) {
    perror("Error synchronizing mapping to disk");
    // 处理错误
    }
    munmap(addr,strlen(addr));
    
    // 读取文件
    // 在子进程中读取文件
    if (fork() == 0) {
        close(fd);
        cout<<strlen(ptr)<<endl;
        int fd_child=open("./my_rw4.txt", O_RDONLY);
        if(fd_child<0){
            perror("File not open");
            return 0;
        }
        char* addr_child=(char*)mmap(nullptr,strlen(ptr),PROT_READ,MAP_FILE|MAP_SHARED,fd_child,0);
        if(addr_child==MAP_FAILED){
            perror("map failed.");
            close(fd_child);
            return 0;
        }
        cout<<(char*)addr_child<<endl;
        
        // *(int *)addr = 2333;
        // printf("val in process %d is %d.\n", getpid(), *(int *)addr);
        munmap(addr_child, strlen((char*)addr_child));
        close(fd_child);
        exit(0);
    }

    wait(nullptr);
    // printf("val in process %d is %d.\n", getpid(), *(int *)addr);
    // munmap(addr, 4);
    close(fd);
    return 0;
}

使用truncate可以增加文件大小,如下:

#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <sys/mman.h>
#include <cstring>
#include <iostream>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
int main() {
    int fd = open("example.txt", O_CREAT | O_RDWR, 0664);

    if (fd == -1) {
        perror("Error opening/creating file");
        return 1;
    }
    
    // 设置文件大小为 4096 字节
    if (ftruncate(fd, 4096) == -1) {
        perror("Error setting file size");
        close(fd);
        return 1;
    }

    // 在这里可以进行对文件的操作,比如使用 mmap 映射到内存

    // 关闭文件
    close(fd);

    return 0;
}

下面是一个使用mmap读取文件的用法:

#include <cstdio>
#include <sys/mman.h>
#include <cstring>
#include <iostream>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
// 使用mmap读写文件

using namespace std;

int main() {
    struct stat state;
    int fd_child=open("./my_rw4.txt", O_RDONLY);
    if(fd_child<0){
        perror("File not open");
        return 0;
    }
    fstat(fd_child,&state);
    cout<<state.st_size<<endl;
    // 获取的文件大小是正确的
    char* addr_child=(char*)mmap(nullptr,state.st_size,PROT_READ,MAP_FILE|MAP_PRIVATE,fd_child,0);
    if(addr_child==MAP_FAILED){
        perror("map failed.");
        close(fd_child);
        return 0;
    }
    cout<<(char*)addr_child<<endl;

    // *(int *)addr = 2333;
    // printf("val in process %d is %d.\n", getpid(), *(int *)addr);
    munmap(addr_child, strlen((char*)addr_child));
    close(fd_child);
    exit(0);

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中集成mmap读写文件可以通过以下步骤实现: 1. 引入依赖:在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> ``` 2. 创建文件操作工具类:创建一个`FileUtils`工具类,用于进行文件读写操作。在该类中,可以使用Java的`MappedByteBuffer`类来实现mmap读写文件的功能。以下是一个简单的示例代码: ```java import java.io.File; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class FileUtils { public static void writeFileWithMmap(String filePath, String content) throws Exception { File file = new File(filePath); RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); FileChannel fileChannel = randomAccessFile.getChannel(); MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, content.length()); mappedByteBuffer.put(content.getBytes()); fileChannel.close(); randomAccessFile.close(); } public static String readFileWithMmap(String filePath) throws Exception { File file = new File(filePath); RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); FileChannel fileChannel = randomAccessFile.getChannel(); MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); byte[] bytes = new byte[(int) file.length()]; mappedByteBuffer.get(bytes); fileChannel.close(); randomAccessFile.close(); return new String(bytes); } } ``` 3. 在Spring Boot应用中使用mmap读写文件:在需要使用mmap读写文件的地方,可以直接调用`FileUtils`工具类中的方法进行文件读写操作。以下是一个简单的示例代码: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); String filePath = "path/to/file.txt"; String content = "Hello, mmap!"; // 写文件 FileUtils.writeFileWithMmap(filePath, content); // 读文件 String fileContent = FileUtils.readFileWithMmap(filePath); System.out.println(fileContent); } } ``` 请注意,以上示例代码仅为演示目的,实际使用时需要根据具体需求进行适当的修改和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值