iT邦幫忙

1

在樹莓派中求生存

  • 分享至 

  • xImage
  •  

前言

最近突然心血來潮想玩玩樹莓派,但估計是全球晶片荒的緣故,竟是一片難求。於是翻出多年前在課堂上購買的迷你樹莓派,這顆樹莓派的型號為 Raspberry Pi Zero W Rev 1.1,單核 CPU (ARMv6Z 32-Bit) 僅 1 GHz 的時脈。記憶體的表定規格為 512 MB,但實際上能用的大概 400 MB 上下。這樣的環境可說是十分凶險,在上面無論是開發或部署,都像是走鋼索般,每步操作都如臨深淵,一個不小心就會看到電源燈無情熄滅,只得拔線重來。之前工作上有接觸到 RPi3,雖然規格比 Zero 好很多,但情況其實也沒比較好。筆者在這邊分享我跟這塊樹莓派相處的經驗,給大家參考。

安裝作業系統

筆者一般透過官方的 RPi Imager 安裝作業系統,現在的 RPi Imager 有很多不錯的功能,例如在安裝之前先設定好 SSH 與 WiFi 的設定,對於沒有設定經驗的使用者來說,實在方便很多。身為一個(自認為)硬派的 Linux 使用者,這麼小一塊樹莓派還要裝桌面環境,實在痛苦。如果不是想要在樹莓派上玩麥塊或者做影像辨識之類的應用,建議安裝沒有桌面環境的 Raspberry Pi OS Lite,透過 SSH 為主進行遠端操作。因為我這塊比較古老,所以只能裝 32 位元。因為以 SSH 遠端操作為主的緣故,所以 SSH 登入資訊與 WiFi 網路連接一定要設定好。

開發環境

一開始沒頭沒腦的,也不太確定要開發什麼,不如我們這邊先裝個 Py ... 不,千萬不要。在這麼嚴苛的環境做開發,已經是很想不開的行為了,別再做這種開發 Python 的自殺舉動。如果是開發一些微服務可能還 OK,但筆者之前部署個 Discord Bot 都覺得十分吃力。筆者這邊為大家演示一下在這塊小樹莓派上跑 Python 是個什麼樣子的想不開法:

pi@raspberrypi:~ $ time pip3 -V
pip 20.3.4 from /usr/lib/python3/dist-packages/pip (python 3.9)

real    0m23.613s
user    0m23.188s
sys     0m0.382s

誠如您所見,光是顯示個 pip 的版本,都要花你快半分鐘。

在這種小型裝置上,使用 C 語言永遠是個好夥伴。筆者幫自己設定的目標,是嘗試在樹莓派上跑個 ONNX 模型的推論,雖然我沒試過,也不確定是否真的可行,但達成這個目標最理想的做法,就是用 C 來實現。

註:最近 NSA 建議從程式語言層級確保記憶體安全,做為 C 語言的替代選擇,推薦使用 Rust 做開發,但筆者對 Rust 所學不多,是個需要繼續修煉的課程。

所以我說那個開發環境

雖算說是用 C 語言開發,難道用 VSCode 的 SSH Remote 套件不行嗎?欸恭喜,問了就沒有:

大概是因為我這塊樹莓派是 32 位元的關係,之前用 RPi3 是可以的,但基本上還是不太推薦這樣直接 Remote 過去,其實 VSCode 的 SSH Remote 是挺消耗資源的,對資源稀少的樹莓派而言更是如此。

如果想要同時享有 VSCode 帶來的便利又想要進行遠端開發,筆者推薦使用 SSHFS (SSH Filesystem) 的方式,將樹莓派裡的專案資料夾掛在自己的系統裡面。

如果作業系統是 Windows 則可以使用 WSL,不過建議把資料夾掛在 \\wsl.localhost\ 底下,運作效率會比較好一點,例如 \\wsl.localhost\Ubuntu\home\username\MyProject 之類的。

以下操作使用「Host 端」代表開發者的 PC,「Remote 端」代表樹莓派開發板:

  1. 首先在 Host 端安裝 sshfs
    • sudo apt update
    • sudo apt install sshfs
  2. 在 Host 端建立資料夾並進行掛載
    • mkdir RemoteProject
    • sshfs pi@@192.168.XXX.XXX:~/RPiProject RemoteProject
  3. 使用 VSCode 快樂開啟工作區
    • cd RemoteProject
    • code .

這樣的做法有幾個優點:

  1. 套件消耗的資源主要在 Host 端,Remote 端基本上只需要負擔網路傳輸。
  2. 可以同時進行 Host 端與 Remote 端的開發。

同時也有些缺點:

  1. 以 VSCode 而言,你要常常去點重新整理的按鈕才能看到檔案的變動。
  2. 環境配置上主要還是看 Host 端,若與 Remote 端有差異,要到編譯期間才看得出來。
  3. SSH 是會斷線的,每次重開工作區都要重新掛載一次。

簡單寫個小程式

我們就來寫個 Hello World! 吧:

// Main.c
#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

在撰寫的過程應該能發現自動完成或錯誤波浪都有正常且快速的運作,如果用 SSH Remote 進去通常不會這麼快。

接下來在兩邊分別進行編譯與執行:gcc Main.c -o Main && ./Main

可以善用 VSCode 的分割 Terminal 或者 tmux 之類的工具來進行雙邊工作:

充滿好奇心的各位,一定會想試試看在 x64 上編譯的程式,在 ARM32 上執行會怎樣:

$ ./Main
-bash: ./Main: cannot execute binary file: Exec format error

鐵定是不給執行的,我們可以用 file 指令來看看兩種編譯出來的執行檔有什麼不一樣:

$ file Main_x86-64
Main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c95fcb56d1a7f19bfafad22d97c41b4f7c1a4cab, for GNU/Linux 3.2.0, not stripped

$ file Main_armv6l
Main: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=d3e4234fa7a2d36d8f417cc58d34cdfa5971bfb3, for GNU/Linux 3.2.0, not stripped

從這些資訊可以看到兩者在位元與 CPU 架構上都不相同。在做跨平台開發的時候,若是管理不慎,自己被搞混的事情也是常常發生。筆者這邊建議使用 uname -m 的指令,搭配常常用來與編譯 C 語言相伴的 Makefile 來處理這個問題:

CC := @/usr/bin/gcc
Arch := $(shell uname -m)
BuildDir := Build/$(Arch)

all: Main.c
	@mkdir -p $(BuildDir)
	$(CC) Main.c -o $(BuildDir)/Main

在兩端分別輸入 make 指令進行編譯,按幾下 VSCode 的重新整理後,可以看到工作區底下出現了一個 Build 資料夾,裡面包含 armv6lx86_64 兩個資料夾,各自包含各自平台的執行檔。

Makefile 除了可以當成進階版的 Shell Script 以外,還會自動幫你分析哪些檔案需要重新編譯。當程式碼規模逐漸上升後,在 RPi 上整個專案重新編譯的時間就會越來越久,善用 Makefile 可以替開發者節省不少時間。

註:如果當你的程式碼規模已經大到樹莓派上沒編譯個三天三夜編譯不完的程度,建議改走 Cross-Compile 這條路線。

結論

我們透過 SSHFS 的方式,避免 VSCode SSH Remote 帶來的資源消耗,同時享受 VSCode 帶來的許多便利,並善用 Makefile 區分兩邊平台的編譯結果,希望這篇文章可以幫助到進行跨平台開發的各位。

補充

留言有網友提到若只是需要一個 ARM32 的開發環境,用虛擬化技術不是更快嗎?確實,如果要進行有規模的開發,採取虛擬化技術是必要的,這樣的技術能夠更充分的利用硬體效能,提高軟體開發的效率。但有些時候虛擬機或容器可能沒辦法直接滿足開發需求,例如:客戶裝置上的生產序號、裝置上感應器的讀取、或者像是外接麥克風實際錄音等等。在虛擬機裡面要實現這些情況,有時並不是那麼容易,即便能夠實現,也很可能會與實際情況有所落差。所以在實際裝置上部署「最低限度」的開發環境,同樣也是重要的課題。

而筆者手邊只有這塊迷你開發板,也不太可能直接拿客戶的裝置來寫文章 XD
在這塊樹莓派上,大多數操作都屬於實驗性質居多。這裡使用 SSHFS 只是作為一個概念性驗證的手法。因此,在這篇文章並不是要強調它是唯一的方法,而是為了提供給有需要的人參考。

筆記

  • 確認樹莓派型號
    • cat /sys/firmware/devicetree/base/model
    • cat /proc/cpuinfo

參考


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
obarisk
iT邦研究生 1 級 ‧ 2022-12-06 12:28:58

要弄一個 arm32 的開發環境還是用 vm 比較快吧

Penut Chen iT邦研究生 5 級 ‧ 2022-12-06 13:02:17 檢舉

沒錯,無論是虛擬機還是容器都會快很多!但是有時客戶的裝置規模就是如此,最終要驗證開發的可行性,還是需要一個相仿的環境做實驗。

這篇文章主要是提供一個不同的角度來選擇開發環境,並提醒大家盡量不要在小型裝置上部署開發環境。

至於 ARM32 只是剛好手邊沒有其他裝置而已,不然我也是很想要一塊 RPi4 以上的開發板 QQ

obarisk iT邦研究生 1 級 ‧ 2022-12-06 13:49:40 檢舉

裝置規模是"執行環境"吧?還是認真要在上面建"開發環境"?

Penut Chen iT邦研究生 5 級 ‧ 2022-12-06 14:13:06 檢舉

最理想的情況,都會希望小型裝置只負責擔任「執行環境」的角色,而開發者可以在高效能裝置上使用「開發環境」。但是在 VM 裡能跑起來,實際裝置卻各種出錯的情況也是很常發生,所以會希望能放個「最低限度」的開發環境在裝置上,而我們希望能在「開發環境」與「開發流暢度」上取得一個權衡。

不過確實筆者過去遇到的實際情況,裝置規模是不如文中的 Pi Zero 如此凶險,只是想提供一個初步的思路去面對手上的裝置。真的要認真進行有規模的開發,還是應該以虛擬化技術、落實版本控制為主軸。使用 SSH Remote 或 SSHFS 只是個實驗性質的小型玩法!

我要留言

立即登入留言