我们可以在内核模块中使用virt_to_phys作为用户空间内存吗?

时间:2017-04-10 13:57:15

标签: memory memory-management linux-kernel malloc linux-device-driver

我将使用$ awk '{for(i=1;i<=NF;i++) if($i ~ /[[:alnum:]]*%$/) {split($i,a,":"); gsub(/*/,"",a[1]);print a[1]}}' f BRK.B PFE NOV C AAPL MMM 在用户应用程序中分配内存,并通过字符驱动程序接口将malloc返回的地址发送到内核模块。

我将使用内核模块中的malloc来固定此内存的页面。

我可以使用get_user_pages_fast获取virt_to_phys返回的地址。 有效吗?如果没有,那么我如何获得适当的实际地址?

我的目标是获取用户空间分配内存的物理地址。 我将传输大小限制为pagesize(4KB)。

3 个答案:

答案 0 :(得分:1)

不,你不能,virt_to_phys将内核虚拟地址转换为物理地址。 linux中存在3种(或4种)地址:

  • 内核虚拟地址:,即物理地址+/-偏移量(PAGE_OFFSET)。
  • 内核物理地址:实际物理地址(由__pa或virt_to_phys函数获取)。
  • 用户虚拟地址:转换为物理地址位于流程的页面表内。

请注意,页面表“布局”取决于处理器的体系结构,因此您需要实现与您所使用的体系结构相对应的软件页面表格

最后一句话,存在的第四种地址是:

  • 总线地址:这是设备看到的地址。

答案 1 :(得分:1)

malloc返回用户虚拟地址。所以我认为你不能在驱动程序中使用malloc返回的地址。

  

virt_to_phys:返回的物理地址是给定内存地址的物理(CPU)映射。仅在通过kmalloc直接映射或分配的地址上使用此功能才有效。这意味着内核使用它将内核虚拟地址(非用户虚拟地址)转换为物理地址

答案 2 :(得分:0)

该程序将帮助您直接访问物理内存。想法是 mmap /dev/mem(RAM)

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

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
        return 0;
    }

    off_t offset = strtoul(argv[1], NULL, 0);
    size_t len = strtoul(argv[2], NULL, 0);

    // Truncate offset to a multiple of the page size, or mmap will fail.
    size_t pagesize = sysconf(_SC_PAGE_SIZE);
    off_t page_base = (offset / pagesize) * pagesize;
    off_t page_offset = offset - page_base;

    int fd = open("/dev/mem", O_SYNC);
    unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
    if (mem == MAP_FAILED) {
        perror("Can't map memory");
        return -1;
    }

    size_t i;
    for (i = 0; i < len; ++i)
        printf("%02x ", (int)mem[page_offset + i]);

    return 0;
}

信用转到Accessing physical address from user space

相关问题