想要修改一个进程的虚拟地址中某个数据的
之前是mmap /dev/mmap来实现的
mapStart = (void volatile *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, pa_base);
在x86_64上运行好好的,但是在arm上提示
Failed to mmap /dev/mem [0xffffffc2eef70000], errno : [22, Invalid argument]
问题1 ===发现pa_base超过1M的就会报这个错,不知道为什么?===
然后我决定用驱动来完成修改工作,pa是物理地址,不是很懂,但是写了下面的代码,也不知道对不对
unsigned long data = FAIL;
unsigned long pa_base = pa << PAGE_SHIFT;
unsigned long pa_offset = pa - pa_base;
struct page *pa_page = mem_map + pa_base;
void volatile *mapStart = (void volatile *)kmap(pa_page);
dbginfo("physical address 0x%lx to kernel address 0x%lx\n", pa, va, data);
if(mapStart == NULL)
{
dbginfo("kmap error\n");
}
else
{
memcpy(&data, mapStart + pa_offset, sizeof(unsigned long));
dbginfo("physical address 0x%lx to kernel address 0x%lx, data 0x%lx\n", pa, va, data);
}
问题2==发现驱动内部,kmap映射出的地址是NULL
我该怎么解决,怎么在内核空间直接读写某个地址,怎么映射呢
memfd 有问题吧。
不是很清楚具体情况,猜测可以检查的点:
memfd
对应的文件有多大?PAGE_SIZE + pa_base
是不是大于文件大小了?memfd
是不是一个普通的文件,是不是用类似POSIX_TYPED_MEM_ALLOCATE
、POSIX_TYPED_MEM_ALLOCATE_CONTIG
的特殊内存对象?如果是的话,这种在各种平台上表现是会有差异的,man
里是这么讲的:
If fildes represents a typed memory object opened with either the POSIX_TYPED_MEM_ALLOCATE flag or the POSIX_TYPED_MEM_ALLOCATE_CONTIG flag, the memory object to be mapped shall be that portion of the typed memory object allocated by the implementation as specified below. In this case, if off is non-zero, the behavior of mmap() is undefined. If fildes refers to a valid typed memory object that is not accessible from the calling process, mmap() shall fail.
再看了下题,题主的问题可能是2吧。
如果验证是第2种造成,可能只能改代码了,最后一个参数只是个偏移量,可以设置为0,并增加映射区域的长度,然后自己访问的时候加上偏移就好。