对于任何好奇的人,这就是我想出的。请注意,这是一个更大、长时间运行程序的模块。此外,它还没有经过审查,无论如何基本上是一个糟糕的黑客。
__attribute__((noinline)) static unsigned int volatile *get_mem(unsigned int addr) {
static void *map = 0 ;
static unsigned prevPage = -1U ;
static int fd = -1;
int poss_err = 0;
register unsigned page = addr & ~MAP_MASK ;
if ( unlikely(fd < 0) ) {
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
longjmp(mem_err, errno);
}
}
if ( page != prevPage ) {
if ( map ) {
if (unlikely((munmap(map,MAP_SIZE) < 0))) poss_err = 1;
}
if (unlikely((map = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page )) == MAP_FAILED)) longjmp(mem_err, errno);
prevPage = page ;
}
return (unsigned int volatile *)((char *)map+(addr & MAP_MASK));
}
static void set_reg(const struct reg_info * const r, unsigned int val)
{
unsigned int volatile * const mem = get_mem(r->addr);
*mem = (*mem & (~(r->mask << r->shift))) | (val << r->shift);
}
// This isn't in the final piece. There are several entry points into this module. Just an example
static int entryPoint(unsigned int value){
if (setjmp(mem_err)!=0) {
// Serious error
return -1;
}
for (i=0; i<n; i++) {
if (strlen(regs[i].name) == strlen(name) &&
strncmp(regs[i].name, name, strlen (name))==0) {
set_reg(®s[i], value);
return value;
}
}
}
这显然不是问题的答案,因为它会检查每个呼叫的条件。