devmem读写物理内存和devkmem读取内核虚拟内存(2)

if (!argv[3]) {
        switch (width) {
        case 8:
            read_result = *(volatile uint8_t*)virt_addr;
            break;
        case 16:
            read_result = *(volatile uint16_t*)virt_addr;
            break;
        case 32:
            read_result = *(volatile uint32_t*)virt_addr;
            break;
        case 64:
            read_result = *(volatile uint64_t*)virt_addr;
            break;
        default:
            bb_error_msg_and_die("bad width");
        }
//        printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n",
//            target, virt_addr,
//            (unsigned long long)read_result);
        /* Zero-padded output shows the width of access just done */
        printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result);------------读取数据并打印。
    } else {
        switch (width) {
        case 8:
            *(volatile uint8_t*)virt_addr = writeval;
//            read_result = *(volatile uint8_t*)virt_addr;
            break;
        case 16:
            *(volatile uint16_t*)virt_addr = writeval;
//            read_result = *(volatile uint16_t*)virt_addr;
            break;
        case 32:
            *(volatile uint32_t*)virt_addr = writeval;
//            read_result = *(volatile uint32_t*)virt_addr;
            break;
        case 64:
            *(volatile uint64_t*)virt_addr = writeval;
//            read_result = *(volatile uint64_t*)virt_addr;
            break;
        default:
            bb_error_msg_and_die("bad width");
        }
//        printf("Written 0x%llX; readback 0x%llX\n",
//                (unsigned long long)writeval,
//                (unsigned long long)read_result);
    }

if (ENABLE_FEATURE_CLEAN_UP) {
        if (munmap(map_base, mapped_size) == -1)
            bb_perror_msg_and_die("munmap");
        close(fd);
    }

return EXIT_SUCCESS;
}

1.3 /dev/mem是如何实现物理地址读写?

/dev/mem在chr_dev_init()中创建,需要创建的节点在devlist[]中。

static const struct memdev {
    const char *name;
    umode_t mode;
    const struct file_operations *fops;
    fmode_t fmode;
} devlist[] = {
#ifdef CONFIG_DEVMEM
    [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
#endif
#ifdef CONFIG_DEVKMEM
    [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
#endif...
};

其中mem_fops对应/dev/mem节点的操作函数。

static const struct file_operations __maybe_unused mem_fops = {
    .llseek        = memory_lseek,
    .read        = read_mem,
    .write        = write_mem,-------------------------------直接对/dev/mem进行读写。
    .mmap        = mmap_mem,---------------------------------对/dev/mem进行mmap映射。
    .open        = open_mem,---------------------------------主要检查权限是否满足CAP_SYS_RAWIO。
#ifndef CONFIG_MMU
    .get_unmapped_area = get_unmapped_area_mem,
    .mmap_capabilities = memory_mmap_capabilities,
#endif
};

static int open_port(struct inode *inode, struct file *filp)
{
    return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}

#define open_mem    open_port

mmap_mem()是mmap()内存映射的执行者,通过将/dev/mem对应的物理地址映射到用户空间虚拟地址。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12046.html