您尚未登录。

楼主 #1 2021-05-07 10:13:57

sprintf
会员
注册时间: 2020-09-11
已发帖子: 50
积分: 45

Linux C用户层用malloc分配的内存的虚拟地址怎么转换为实际物理地址?

问题说明: 目前在f1c200s上运行的tina3.5。看了tina的播放器例子,发现要使用disp设备需要提供物理地址进行设置方可正常使用,
网上找到一段转换代码如下,实际使用的时候,似乎是计算的不对,但是有一部分好像是对的。就是设置后往虚拟地址写东西,屏幕有部分有反应。

void mem_addr(unsigned long vaddr, unsigned long *paddr)
{
        int pageSize = getpagesize();//调用此函数获取系统设定的页面大小

        unsigned long v_pageIndex = vaddr / pageSize;//计算此虚拟地址相对于0x0的经过的页面数
        unsigned long v_offset = v_pageIndex * sizeof(uint64_t);//计算在/proc/pid/page_map文件中的偏移量
        unsigned long page_offset = vaddr % pageSize;//计算虚拟地址在页面中的偏移量
        uint64_t item = 0;//存储对应项的值

        int fd = open("/proc/self/pagemap", O_RDONLY);
        if(fd == -1)//判断是否打开失败
        {
                printf("open /proc/self/pagemap error\n");
                return;
        }

        if(lseek(fd, v_offset, SEEK_SET) == -1)//将游标移动到相应位置,即对应项的起始地址且判断是否移动失败
        {
                printf("sleek error\n");
                return;
        }

        if(read(fd, &item, sizeof(uint64_t)) != sizeof(uint64_t))//读取对应项的值,并存入item中,且判断读取数据位数是否正确
        {
                printf("read item error\n");
                return;
        }

        if((((uint64_t)1 << 63) & item) == 0)//判断present是否为0
        {
                printf("page present is 0\n");
                return ;
        }

        uint64_t phy_pageIndex = (((uint64_t)1 << 55) - 1) & item;//计算物理页号,即取item的bit0-54

        *paddr = (phy_pageIndex * pageSize) + page_offset;//再加上页内偏移量就得到了物理地址

        close(fd);
}

最近编辑记录 sprintf (2021-05-07 10:18:35)

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn