2017-02-17 74 views
3

我正在执行一组活动以确保Redis在一组嵌入式系统(包括Raspberry PI)中运行良好。为了修复执行未对齐内存访问的Redis的某些代码路径(由于Redis 3.2中引入了更改),我试图强制PI在未对齐的内存访问上记录消息,或者在进程发送信号时有时候是这样的。通过这种方式,我可以确保Redis能够在未对齐的访问违规的情况下运行良好,并且在平台上可以更快地运行,而这种访问可以执行但速度较慢。 ARM V6,在PI V1所使用的一个,显然能够处理未对齐的存储器访问,所以如果使用下面的命令,以便配置Linux到的信号发送到处理执行对齐访问:Raspberry PI版本1未检测到未对齐的访问

echo 4 > /proc/cpu/alignment 

然后运行下面的程序:

#include <stdio.h> 
#include <stdint.h> 

int main(int argc, char **argv) { 
    char *buf = "foobareklsjdfklsjdfslkjfskdljfskdfjdslkjfdslkjfsd"; 
    uint32_t *l = (uint32_t*) (buf+1); 
    printf("%p\n", l); 
    printf("%d\n", (int)*l); 
    return 0; 
} 

我看不到由处理接收到的任何信号,或者在/proc/cpu/alignment递增的计数器。

我的猜测是,这是由于ARM v6能够自动处理未对齐的地址,如果给定的CPU配置标志被设置。我的问题是,我的假设是否正确?如果是这样,如何强制PI版本1在未对齐访问的情况下实际引发异常,以便Linux内核根据/ proc/cpu/alignment可以捕获它并发送信号,记录访问等等。设置?

编辑:值得注意的是,即使在ARM v6中,并非所有的指令都可以执行未对齐的访问。例如STMDB,STMFD,LDMDB,LDMEA和类似的多字指令确实会引发异常,并且会被Linux内核困住。

回答

4

我想我终于找到我的答案:

  1. 是的,我是正确的,直到字长ARM V6(或更高),以静默方式处理未对齐的访问,以便不产生陷阱,是完全透明的为Linux内核。将不会记录任何内容,也不会增加/proc/cpu/alignment中的陷阱计数器。
  2. AFAIK我不能强制内核来捕获字大小的未对齐访问,因为显然应该配置CPU以便在每种情况下捕获未对齐的地址,但Linux内核不会AFAIK,可能是因为在内核本身内部存在对齐不安全的代码。检查Linux内核源代码确实可以看出:

    if (cpu_is_v6_unaligned()) { 
         set_cr(__clear_cr(CR_A)); 
         ai_usermode = safe_usermode(ai_usermode, false); 
    } 
    

    这意味着该SCTLR.A总是被清零,所以没有陷阱 将不对齐的生成访问ARM V6可以处理。

  3. 有很多指令在与未对齐的地址一起使用时会产生陷阱,例如多存储/加载指令,加载和存储双精度值。

  4. 不过,也有指令GCC(出厂默认树莓Linux发行版本)将愉快地制作不是由Linux内核正确处理,这将导致即使产生SIGBUS当/proc/cpu/alignment设为修复访问。

所以点数4基本上意味着,它不是解决方案,以在ARM上运行6版只是让Linux内核为我们处理未对齐的地址是一个好主意,即使在未对齐的地址对性能的影响是不是一个问题:程序仍然会崩溃,因为并不是所有的指令都被处理。

如何在程序中可靠地找到所有未对齐的访问仍然是一个尚未解决的问题AFAIK,因为不幸的是,其他美妙的valgrind程序从未实现过这个功能。过去我不得不使用QEMU模拟Sparc,但这是一个非常缓慢的过程。 Valgrind将是做这件事的微不足道的方法。

+1

ARMv4和v5也允许进行未对齐的访问,某些arm core在默认情况下启用其他的不启用,无论是哪种情况,您都可以启用或禁用它。对于未对齐的访问,较旧的内核行为与预期的不同/奇怪,它会旋转单词中的字节,而不是浸入下一个地址。这是非常有意义的,因为你是如何在字节存取(或半字)的零字节通道上获得正确的字节,不止一种方式来表示该猫的皮肤。 –

+1

请注意,如果您只是希望在软件中发现通常存在未对齐的访问,而不是专门针对ARM,则可以让x86陷入Linux下未对齐的访问。 – EOF

+0

EOF是的,我发现,如果你指的是AC寄存器。但是,如果不通过gdb set命令,我没有找到一种可靠的方法在我的程序中实现它。 – antirez