一、硬件平臺
MT7620(A9內核)
二、軟件平臺
1、Ubuntu 12.04
2、openwrt 官方15.05版本SDK開發包
三、功能說明
本文章主要說明如何在openwrt 系統上,編譯node.js功能以及簡單的使用。對於node.js運行之後,產生的"Illegal instruction"如何處理的問題。
四、編譯步驟
1、node.js功能在 “ Languages --> Node.js --> node”中。故進入到openwrt的SDK包目錄,執行“make menuconfig”命令,選中Languages 選項,如圖4-1所示。
圖4-1 menuconfig選項
2、在Languages菜單中,選擇node,如圖4-2所示。
圖4-2 Languages菜單
3、在node.js中,選擇node選項,如圖4-3所示。
圖4-3 node.js菜單
4、選擇node完畢之後,保存內核配置,退出。執行編譯命令 “make V=s”,編譯出內核。
五、測試node.js功能
5.1、查看版本號
將編譯出的內核,燒錄到開發板上,運行“node -v”,查看版本號。
圖5-1 查看node版本號
5.2、測試node.js語法功能
在/tmp/目錄下,編寫一個測試程序, “vi /tmp/test.js”。測試程序的內容爲一個簡單的輸出信息,代碼如下。
console.log("hello world");
保存完文件,用node運行該文件,結果如圖5-2所示,運行之後,
錯誤提示“Illegal instruction”。
圖5-2 Illegal instruction錯誤報告
六、Illegal instruction 錯誤分析
6.1 Illegal instruction 介紹
對於“Illegal instruction”錯誤,即SIGILL,
是POSIX標準中提供的一類錯誤。 從名字上看,SIGILL是啓動的某個進程中的某一句不能被CPU識別成正確的指令。 此類錯誤是由操作系統發送給進程的,在進程試圖執行一些形式錯誤、未知或者特權指令時操作系統會使用SIGILL信號終止程序。 SIGILL對應的常數是4。
6.2 錯誤原因彙總
6.2.1 將不正確的數據寫入代碼段
進程在代碼段中的數據是要被作爲一個指令執行的。 若不小心覆蓋了已有的代碼段,可能會得到錯誤格式的指令。這種錯誤尤其在Just-In-Time即時編譯器中最可能出現。
同樣,如果不小心覆蓋了棧上活躍記錄中的返回地址,程序就可能根據這個錯誤地址,執行沒有意義的內存中的數據,進而操作。進一步可以認爲,任何導致數據錯誤的問題都可能帶來illegal instruction問題。比如硬盤發生故障。
6.2.2 指令集的演進
比如SIMD指令,自從奔騰4開始有MMX,X86的芯片就開始不停的增加和拓寬SIMD支持,SSE、SSE2、SSE3、SSE42、AVX、AVX2。 默認情況下,很多編譯器都在O2或者O3中開了自動向量化,這就導致很多在新體系結構中編譯的可執行程序,在老機器上運行時會有illegal instruction問題。
6.2.3 工具鏈bug
對於普通C語言通過編譯器生成的可執行程序。一般都已經通過嚴格的測試,不會隨便發生這種問題。 所以如果你遇到這種錯,並且試過了靜態鏈,而且程序中沒有嵌入式彙編,基本可以斷定是工具鏈出了問題。 編譯器、彙編器或者鏈接器。
6.2.4 訪存對齊或浮點數格式問題
根據Heiher的經驗,請注意出現錯誤的指令可能和訪存地址指令有關。 另外,浮點數的格式是否符合IEEE的標準也可能會有影響。
6.3 錯誤分析
(1)執行的test.js文件,爲一個簡單的打印信息,不涉及到任何的堆棧操作和錯誤格式的指令,故不可能爲“將不正確的數據寫入代碼段”錯誤。
(2)node.js工具,採用gcc2.21編譯,而且與內核一起編譯,採用的同一個工具鏈,所以不可能爲“指令集的演進”錯誤。
(3)採用的交叉工具鏈爲openwrt SDK開發包提供的標準工具鏈"gcc 2.21"版本,所以不可能爲“工具鏈bug”錯誤。
(4)運行的程序爲訪問地址操作,所以不是“訪問內存對齊”的問題,只能爲“浮點數格式”問題。而且,經過查找SDK包的內核配置,發現確實沒有配置"MIPS FPU Emulator"選項。
最終,得出結論,是內核配置中,沒有配置芯片的FPU,導致浮點運算有問題。
七、Illegal instruction 錯誤解決方案
對於MIPS架構的FPU,配置路徑爲“kernel type --> MIPS FPU Emulator”。
1、在openwrt的SDK目錄下,運行命令“make kernel_menuconfig”,選擇配置“kernel type”,如圖7-1所示。
圖7-1 內核配置菜單
2、在"kernel type"中,選中"MIPS FPU Emulator",如圖7-2所示。
圖7-2 選擇MIPS FPU Emulator
3、配置完畢之後,保存退出,並執行編譯命令“make V=s”,編譯出新的內核。
4、將新的內核燒錄到開發板上,再次編寫測試程序,並運行,結果如圖7-3所示,成功的輸出了測試日誌“hello world”,說明問題得以解決。
圖7-3 測試node.js 功能