qiubo666 2020-06-24 10:40 采纳率: 0%
浏览 286

linux下用户程序通过mmap映射驱动的内存,使用O_DIRCTE模式创建文件,write到文件时报Bad addreee

下面为用户层函数代码:

void simple_test(char *filename, int dma_fd)
{
    int file_fd
    void *user_mem = NULL;
    int pagesize = 0;
    int rc;

    file_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_DIRECT, 0666);

    user_mem = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, dma_fd, 0);
    if (user_mem == (void*) -1) 
    {
        fprintf(stderr, "mmap: %s\n", strerror(errno));
        exit(-1);
    }

    printf("user_mem %p\n", user_mem);

    rc = write(file_fd, user_mem, pagesize);
    if (rc < 0)
    {
        perror("write file");
    }
    else if(rc != pagesize)
    {
        printf("Write file fail 0x%lx != 0x%lx.\n", rc, pagesize);
    }   

    rc = munmap(user_mem, pagesize); 
    if (rc)
    {
        perror("munmap");
    }   
}

内核驱动使用dma_alloc_coherent分配的内存,使用dma_mmap_coherent映射到用户空间。
执行测试函数simple_test时报write file: Bad addree

映射的地址和长度都是页大小的整数倍。不使用O_DIRECT时没有错误。

  • 写回答

2条回答

  • 幸福快乐fyf 2023-07-01 19:17
    关注

    在Linux下,使用O_DIRECT模式创建文件时,需要满足一些特定的要求。其中之一是写入文件的缓冲区必须是页对齐的,而且长度必须是页大小的整数倍。根据您提供的代码,可能是由于没有正确对齐缓冲区导致了Bad address错误。

    为了解决这个问题,您可以执行以下步骤:

    1. 获取系统的页大小:使用sysconf函数获取系统的页大小,以确保对齐缓冲区。
    2. 对齐缓冲区:将mmap函数中的大小参数pagesize修改为页大小的整数倍。

    下面是修改后的示例代码:

    void simple_test(char *filename, int dma_fd)
    {
        int file_fd;
        void *user_mem = NULL;
        int pagesize = 0;
        int rc;
    
        pagesize = sysconf(_SC_PAGESIZE);
    
        file_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_DIRECT, 0666);
    
        user_mem = mmap(0, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, dma_fd, 0);
        if (user_mem == (void*) -1) 
        {
            fprintf(stderr, "mmap: %s\n", strerror(errno));
            exit(-1);
        }
    
        // 对齐缓冲区
        void *aligned_mem = (void *)(((unsigned long)user_mem + pagesize - 1) & ~(pagesize - 1));
    
        printf("user_mem %p\n", aligned_mem);
    
        rc = write(file_fd, aligned_mem, pagesize);
        if (rc < 0)
        {
            perror("write file");
        }
        else if(rc != pagesize)
        {
            printf("Write file fail 0x%lx != 0x%lx.\n", rc, pagesize);
        }
    
        rc = munmap(user_mem, pagesize * 2);
        if (rc)
        {
            perror("munmap");
        }
    }
    

    根据您的具体情况进行适当的修改和调整。确保对齐缓冲区的大小是页大小的整数倍

    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题