c - 如何分配物理内存块?
问题描述
如标题所示,我需要分配至少 32MB 的物理内存块。我有一个硬件,可以在给定的物理地址保存它的跟踪数据,其中包含 32MB 块。所以我想用虚拟地址分配足够的空间并翻译它的地址,但我忘记了物理内存中的页面没有存储在另一个旁边。
现在我有这个代码。
#define MEGABYTE 1048576
#include <fcntl.h> /* open */
#include <stdint.h> /* uint64_t */
#include <stdio.h> /* printf */
#include <stdlib.h> /* size_t */
#include <unistd.h> /* pread, sysconf */
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct {
uint64_t pfn : 54;
unsigned int soft_dirty : 1;
unsigned int file_page : 1;
unsigned int swapped : 1;
unsigned int present : 1;
} PagemapEntry;
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
{
size_t nread;
ssize_t ret;
uint64_t data;
uintptr_t vpn;
vpn = vaddr / sysconf(_SC_PAGE_SIZE);
nread = 0;
while (nread < sizeof(data)) {
ret = pread(pagemap_fd, &data, sizeof(data) - nread,
vpn * sizeof(data) + nread);
nread += ret;
if (ret <= 0) {
return 1;
}
}
entry->pfn = data & (((uint64_t)1 << 54) - 1);
entry->soft_dirty = (data >> 54) & 1;
entry->file_page = (data >> 61) & 1;
entry->swapped = (data >> 62) & 1;
entry->present = (data >> 63) & 1;
return 0;
}
/* Convert the given virtual address to physical using /proc/PID/pagemap.
*
* @param[out] paddr physical address
* @param[in] pid process to convert for
* @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure
*/
int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr)
{
char pagemap_file[BUFSIZ];
int pagemap_fd;
snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%ju/pagemap", (uintmax_t)pid);
pagemap_fd = open(pagemap_file, O_RDONLY);
if (pagemap_fd < 0) {
return 1;
}
PagemapEntry entry;
if (pagemap_get_entry(&entry, pagemap_fd, vaddr)) {
return 1;
}
close(pagemap_fd);
*paddr = (entry.pfn * sysconf(_SC_PAGE_SIZE)) + (vaddr % sysconf(_SC_PAGE_SIZE));
return 0;
}
int is_changed(uint8_t *pBuffer, uint64_t size)
{
printf("size = %ld\n", size);
for (uint64_t i = 0; i < size; i++)
{
if(pBuffer[i] != 'A')
{
printf("Found it!!!\n");
printf("Index = %ld\n",i);
return 1;
}
}
printf("Nothing found!\n");
return 0;
}
uint8_t *virtual_mem_addr = NULL;
uint8_t *physical_mem_addr = NULL;
uint64_t mem_size = 0;
pid_t pid = 0;
char* vaddr = NULL;
uintptr_t paddr = 0;
FILE *f = NULL;
int main(int argc, char const *argv[])
{
uint64_t pFile;
struct stat statbuf;
unsigned char *mmapPointer;
uint32_t file_size = 0;
pid = getpid();
if (argc < 2)
{
printf("Usage %s <filename>\n", argv[0]);
return 1;
}
pFile = open(argv[1], O_RDWR | O_SYNC);
if(pFile <= 0)
{
printf("Error opening %s.\n", argv[1]);
return 1;
}
if(fstat(pFile,&statbuf) < 0)
{
printf("fstat error\n");
return 1;
}
mmapPointer = mmap(NULL,statbuf.st_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, pFile,0);
printf("mmapPointer = %p\n",mmapPointer);
printf("pid %ju\n", (uintmax_t)pid);
printf("%c\n",mmapPointer[0]);
printf("mmapPointer After loop = %p\n",mmapPointer);
if (virt_to_phys_user(&paddr, pid,(uintptr_t)mmapPointer))
{
fprintf(stderr, "error: virt_to_phys_user\n");
return EXIT_FAILURE;
};
printf("paddr = 0x%jx\n", (uintmax_t)paddr);
//WAITING FOR CHANGE
printf("Press key to continue.\n");
getchar();
// //CHECK IF SOMETHING HAS CHANGED
is_changed(mmapPointer, 32*MEGABYTE);
if(munmap(mmapPointer,statbuf.st_size) < 0)
{
perror("Error un-mapping the file\n");
close(pFile);
return 1;
}
close(pFile);
return EXIT_SUCCESS;
}
它使用 mmap() 为缓冲区文件(充满“A”字节的 64MB 文件)分配虚拟内存,并使用 virt_to_phys() 将其虚拟地址转换为物理地址。接下来,当有“WAITING FOR CHANGE”评论时,我试图用另一个程序将一些字节保存到这个地址。我现在已经用busybox devmem对其进行了测试,当读取前16KB的内存时,我已经读取了缓冲区文件中的内容,但之后它读取了一些乱码数据,因此可以确认物理内存在其他地方分配了下一页记忆。
所以我的问题是如何分配物理内存空间中相邻的 32MB 内存块。更好的问题是:这甚至可能吗?
解决方案
推荐阅读
- python - 安装柯南包没有要求?
- node.js - 带 POST 和不带 POST 的电报 sendMessage
- pagespeed-insights - 不同站点的不同字段数据,有人知道为什么吗?
- javascript - 如何弹出隐藏溢出的祖先之外的嵌套子组件?
- c - 我分配的内存数组上出现意外的数组长度
- powershell - Active Directory ADUser whenCreated 属性
- python - 如何始终如一地定时打印
- sql - 在 SQL 中选择具有产品组合的城市
- hive - hive alter table concatenate 命令风险
- react-native - Firebase 实时数据库高级安全规则