2017-02-17 26 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