python移植到arm的單板
python移植到arm的單板
2017年09月22日 09:05:55 mania_yan 閱讀數:3068
注:下文的CSU是我們一個嵌入式單板的名稱。
1 前言
作者的話:
本人非常喜歡python,一直夢想可以移植到CSU中。但是python誕生之初並沒有想到要應用在嵌入式領域,因此,python的交叉編譯比較複雜。python的交叉編譯花費了我一些時間進行摸索,這篇文章是在查閱了N多資料,進行了N多嘗試後成功的,就在想徹底放棄的時候,NEVER GIVE UP的信念讓我進行前進,而恰恰是這前進的一步,轉暗為明,相繼研究出來CSU的NFS與CSU的Python!這是讓自己非常振奮的!
2 交叉編譯
這裡以python2.7.6進行陳述。
下載python的linux版本原始碼包,解壓到/opt中。
2.1 更新虛擬機器上的python版本
為了最大的穩定性,建議更新虛擬機器上的版本與交叉編譯的版本一致。由於下載的原始碼包版本肯定是最新的,因此,順便更新一下虛擬機器的python版本也是一件好事。
傳統三部曲。
./configure
make
make install
2.2 配置arm的configure
由於原始碼包需要生成pc版的python和arm版的python,因此,需要隔離開,這個非常關鍵。
pc版採用原有路徑,不改變。
arm則在原始碼包下
mkdir arm_build
由於configure會在當前目錄下生成Makefile等檔案,因此,不能在原始碼包下直接configure,必須在arm_build裡執行。這點非常重要。
cd arm_build
由於交叉編譯中,需要明確如下兩個變數的值,因此,這裡必須人工定義。ptmx就是虛擬串列埠的意思,由於我的單板以後要用到這個,因此,設為yes。
設為no一樣是可以的。
echo ac_cv_file__dev_ptmx=yes > config.site
echo ac_cv_file__dev_ptc=yes >> config.site
export CONFIG_SITE=config.site
建好arm版python要安裝到的資料夾。
arm_install=/opt/arm_python
mkdir $arm_install
configure如下:
../configure --host=arm-none-linux-gnueabi --build=i686-linux-gnu --target=arm-none-linux-gnueabi --disable-ipv6 --prefix=$arm_install --enable-shared --silent
其中,arm的gcc採用2011版本;
由於ipv6支援有問題,因此,必須關閉;
--silent去掉configure過程中的垃圾資訊,只輸出warning及以上的關鍵資訊,我特別喜歡這個。
--build是必須填的,怎麼知道這個build資訊呢,最簡單的方法就是
gcc –v
裡面會有gcc的configure資訊,裡面就有--build的資訊,複製過來就萬無一失。
--target其實可以不寫,系統可以猜出來的,但這裡還是寫上。
2.3 pgen準備
這個非常關鍵。
在configure之後make或make Parsr/pgen。
可以在arm_build的Parser資料夾裡發現pgen這個執行檔案,它是python的語法分析器之類東西,但問題來了。
這個東西是不能用的,因為是交叉編譯版本的pgen,在虛擬機器下用不了。
最簡單的解決方法如下:
回到原始碼包路徑
cd ../
生成pc版本的pgen
make Parser/pgen
複製到arm_build的Parser裡面
cd arm_build
cp ../Parser/pgen Parser
下面這一步非常關鍵而且非常巧妙
touch –t 12312359 Parser/pgen
意思是:將pgen檔案的日期改為今年的最後一分鐘生成的。
為什麼需要這一步?
很簡單:
因為,arm版python在make時,會生成它的pgen,就會把剛才複製過來的給替換掉了,改了未來的時間,就會忽略跳過,非常巧妙的技巧!
2.4 make && make install
現在可以make(或make python)了。
我喜歡加上--silent,這樣可以減少很多垃圾資訊。
make完成後,注意:
這裡,使用make install一般會出錯,顯示缺失_struct的型別錯誤。
使用make -i install 才能搞定。
-i 就是ignore錯誤的意思,繼續前進。這裡可能的問題是:前面需要某模組,但是install中卻在後面才安裝這個模組,導致了前面找不到模組的錯誤,其實,整個完成後,是完整的。
這一招對這種時序問題,或install中出現的時序問題比較難解決時,能幫上大忙。
現在,檢視/opt/arm_python這個安裝目錄,可以發現已經有相關python檔案了。
3 第三方庫
python容易使用的一大特點就是自由開放的庫很多,官方不可能全部納入自己的標準庫中,因此,安裝自己需要的第三方庫是必要的。
舉例:
這裡安裝第三方xlrd庫,這個庫可以非常方便的讀取excel檔案的內容,即使不在windows下,即使沒有安裝excel,也可以,而且速度非常的快。
下載原始碼包後解壓,cd到那個路徑下。
python setup.py install
就可以完成第三方庫的安裝了。這裡的install其實就是包括build和install。
對於虛擬機器,會安裝到
/usr/local/lib/python3.3/site-packages
第三方庫基本預設安裝在site-packages裡。
那如何安裝到我們的arm的python裡呢。
很簡單:
python setup.py install --prefix=/opt/arm_python
(預設情況下,這個字首為/usr/local/)
如果沒有正確安裝,當程式需要這個庫時,會報找不到模組的error。
4 應用
由於python的庫檔案很大,直接拷貝到CSU是不現實的。裁剪庫也很麻煩,而且消弱了功能。因此,這裡採用NFS。python的bin、lib等檔案,以及自己編寫的程式碼檔案都放在虛擬機器上。CSU通過NFS使用python即可。
CSU側:
mkdir /mnt/python
mount –o nolock 10.9.102.23:/opt/arm_python /mnt/python
在/etc/profile裡
在export PATH一行後面加入
:/mnt/python/bin
在export LD_LIBRARY_PATH 一行後面加入:/mnt/python/lib
這樣就可以使用python了。
python –V就可以看到python的版本資訊了。
python回車後
就可以進入python的shell了,可以在命令中輸入python語句。
由於這個CSU上的python的shell非常不好用,打錯字無法修正,⊙﹏⊙b汗,因此,我一般都在虛擬機器上寫程式碼,CSU上執行就行了。(注,python的shell退出方式是輸入exit()指令)
例如:
mkdir /opt/arm_python/code
在code寫入helloworld.py的檔案
在CSU中:
python /mnt/python/code/helloworld.py
就可以看到輸出了。
5 python3的移植
同python2。
虛擬機器是支援同時安裝兩個版本的python的,它們的路徑會通過版本號進行區分。
arm版的python也一樣,在/opt/arm_python會進行版本的區分。
預設python連結指向python2,如果需要更改,rm後ln到python3即可。
6 懶人時刻
又是將書變薄的時候了,以下是精華,即自動化交叉編譯指令碼。
#prepare
echo "prepare stage"
arm_install=/opt/arm_python
arm_build=`pwd`/arm_build
mkdir $arm_build
mkdir $arm_install
cd `pwd`
#arm comfigure
echo "arm confiure stage"
cd $arm_build
echo ac_cv_file__dev_ptmx=yes > config.site
echo ac_cv_file__dev_ptc=yes >> config.site
export CONFIG_SITE=config.site
../configure --host=arm-none-linux-gnueabi --build=i686-linux-gnu --target=arm-none-linux-gnueabi --disable-ipv6 --prefix=$arm_install --enable-shared --silent
#pc pgen
echo "pc pgen stage"
cd -
./configure --silent
for args in [email protected]
do
if [ $args = "all" ];then
make --silent && make install --silent
break
fi
done
make Parser/pgen --silent
cd -
mkdir Parser
cp ../Parser/pgen Parser/
#change the pgen time,
# or else the cross compile will replace this pc version pgen. important!!
touch -t 12312359 Parser/pgen
#make
echo "make stage"
make python --silent && make -i install
#make it smaller
#arm-none-linux-gnueabi-strip -s $arm_install/bin/python3.3
exit 0
使用方法:
chmod +x arm_python
複製到原始碼包路徑下(或ln到原始碼包路徑下);
執行./arm_python 即可。
預設安裝在/opt/arm_python裡。
(當加入引數all時,指令碼會順便更新虛擬機器上的python)
[Guangwei] 上述指令碼是為32位Ubuntu寫的,如果是64為Ubuntu,還需要注意2點:
1。 configure 的“--build=x86_64-linux-gnu”,這個要用“gcc -v”檢視。
2。 arm gcc是32位的編譯器,不能直接在64位的機器上執行,需要下載支援庫。可以參考如下解決方案,
arm-hisiv600-linux-gcc編譯出現提示:No such file or directory
實際就是:64位ubuntu不相容32bit工具問題。
解決辦法如下:
apt-get update
sudo apt install lib32z1-dev
apt-get install lib32z1 lib32ncurses5
apt-get install lib32stdc++6
#apt-get install lib32bz2-1.0
apt-get install gcc-multilib g++-multilib
7 附錄(效能測評)
7.1 不同cpu與系統的對比
執行如下測評語句:
import time
start_time=time.clock()
for i in range(1000):
print('good')
end_time = time.clock()
print('total time is ', end_time-start_time)
結果對比:
CPU |
OS |
Time |
奔騰E6700(酷睿core2) |
Windows7 |
0.03s |
奔騰E6700(酷睿core2) |
Virtual Ubuntu |
0.01s |
AMD炫龍雙核 |
Ubuntu |
0.003s |
AT9260(Arm9) |
Linux |
0.6s |
AM335(A8) |
Linux |
0.18s |
結果在我的預測範圍裡,即CSU的處理能力只有主流臺式2核cpu的幾百分之一,屬於可以接受的範圍。
(有趣的是,ubuntu的執行速度遠高於windows!python雖然是跨平臺語言,但是在linux環境下,卻有明顯的優勢)
另一個將資料字典自動轉為XML的程式對比:
win7:0.35s
A8:8s
7.2 python與C的對比
執行1000次相加與輸出:
C語言程式碼如下:
1 #include <stdio.h>
2 #include <sys/time.h>
3 void main(void){
4 struct timeval start,end;
5 gettimeofday(&start,NULL);
6 int i,sum=0;
7 for(i=0;i<1000;++i){
8 sum+=i;
9 printf("%d\n",sum);
10 }
11 gettimeofday(&end,NULL);
12 printf("total time is %d\n",1000000*(end.tv_sec-start.tv_sec)+end.tv _usec-start.tv_usec);}
Python程式碼如下:
1 import time
2 start_time = time.clock()
3 sum=0
4 for i in range(1000):
5 sum=i+sum
6 print(sum)
7 end_time = time.clock()
8 print('time is ',end_time-start_time )
C一共使用:34毫秒;
Python一共使用:180毫秒。
Python為C速度的20%左右,屬於可以接受的範圍內