這裡介紹如何調整樹莓派的 swap 記憶體交換空間大小,以解決記憶體不足當機的問題。

現在最新的樹莓派 Raspberry Pi 3 硬體使用 1.2GHz 四核心的 CPU,內建藍芽與 WiFi,已經可以直接當作簡單的小電腦來用了,既省空間、成本又便宜,不過由於它的記憶體只有 1GB,以我個人的狀況而言,有時候這樣的設定在 Raspberry Pi 3 上多開幾個 Chromium 的網頁就會不夠用,甚至接近當機的情形,這一點就比較困擾一些。


而現在的記憶卡與 USB 隨身碟都很便宜,我們可以利用記憶卡或隨身碟的空間來作為 swap,雖然這類的儲存空間沒有實體記憶體來的有效率,不過至少可以解決樹莓派記憶體不足導致當機的問題。

調整 Swap 交換空間大小

樹莓派的 swap 交換空間是使用 dphys-swapfile 服務來管理的,更改 swap 交換檔的大小設定可透過 /etc/dphys-swapfile 設定檔來處理:

# set size to absolute value, leaving empty (default) then uses computed value
#   you most likely don't want this, unless you have an special disk situation
CONF_SWAPSIZE=100

CONF_SWAPSIZE 是設定 swap 檔案的大小,單位是 MB,其預設是 100,這個預設值對於有 1GB 記憶體的樹莓派來說算是有點小,如果不小心記憶體使用太多的話就容易會出問題。

我們可以將這個值調高一點,或是直接把這一行設定註解起來(不要設定),如果不要設定的話,dphys-swapfile 會自己計算最適當的 swap 大小,必要時也會自動調整 swap 檔案大小。

調整好 CONF_SWAPSIZE 之後,重新啟動 dphys-swapfile 服務,讓新設定生效:

sudo service dphys-swapfile restart

檢查新的 swap 狀態:

swapon -s
Filename                                Type            Size    Used    Priority
/var/swap                               file            1914876 5332    -1

這裡讓 dphys-swapfile 自行計算出來的 swap 大小大約是 2GB 左右,預設就是實體記憶體的兩倍,這個倍數可以用 CONF_SWAPFACTOR 來調整:

# set size to computed value, this times RAM size, dynamically adapts,
#   guarantees that there is enough swap without wasting disk space on excess
CONF_SWAPFACTOR=2

另外我們也可以靠著 CONF_MAXSWAP 參數來設定自動配置 swap 空間的大小上限值:

# restrict size (computed and absolute!) to maximally this limit
#   can be set to empty for no limit, but beware of filled partitions!
#   this is/was a (outdated?) 32bit kernel limit (in MBytes), do not overrun it
#   but is also sensible on 64bit to prevent filling /var or even / partition
CONF_MAXSWAP=2048
一般來說 swap 交換空間不適合建立在記憶卡或 USB 隨身碟這類的快閃記憶體(flash)之中,因為這樣會大幅增加快閃記憶體的讀寫次數,讓使用壽命跟著縮短,不過如果現在很多的記憶卡與隨身碟都有終身保固了,所以壽命的問題影響就不大。

使用 USB 隨身碟作為 Swap 空間

如果手上剛好閒置的 USB 隨身碟,也可以將 USB 隨身碟格式化之後,掛載至樹莓派上,除了當作額外的儲存空間,也可以將 swap 交換空間放在上面。

掛載 USB 隨身碟

若要讓 USB 隨身碟跟普通硬碟一樣可以固定掛載在系統的固定路徑上,可以仿照一般新增 Linux 硬碟的作法,將 USB 隨身碟格式化成 ext4 檔案系統,然後使用 UUID 的方式寫入 /etc/fstab 中,這樣樹莓派就可以多一個固定的儲存空間。

首先使用 gparted 磁碟分割工具,把 USB 格式化成 ext4 檔案系統,接著把格式化好的 USB 隨身碟插入樹莓派,正常來說樹莓派偵測到新的 USB 隨身碟之後,會自動進行掛載,不過這種自動的方式會將隨身碟掛載至 /media/pi/ 這種使用者的路徑之下,這個掛載點是可以被一般使用者卸載的,若想要把 swap 交換空間放在上面的話,會有大問題,所以我們必須把 USB 隨身碟寫在系統層級的掛載點。

使用 blkid 查看 USB 隨身碟的 UUID:

blkid
/dev/mmcblk0p1: SEC_TYPE="msdos" LABEL="boot" UUID="7F22-B6C1" TYPE="vfat" PARTUUID="c0ed4be9-01"
/dev/mmcblk0p2: UUID="402bfe3d-37db-48a7-a515-31edccf953df" TYPE="ext4" PARTUUID="c0ed4be9-02"
/dev/sda1: UUID="2ce396ed-4788-4bcc-a1a5-814966f6cfbb" TYPE="ext4" PARTUUID="e6259569-962f-4108-b10c-9044a5f74d17"

以我的這一個 USB 隨身碟而言,磁碟的路徑是 /dev/sda1,而其 UUID 則為 2ce396ed-4788-4bcc-a1a5-814966f6cfbb

接著修改 /etc/fstab 設定檔,以 UUID 的方式加入這個 USB 隨身碟的掛載設定:

UUID=2ce396ed-4788-4bcc-a1a5-814966f6cfbb	/usbdisk	ext4	defaults	0	0

這裡我設定將這個 USB 隨身碟掛載至 /usbdisk,這個位置可以自己隨意取,接著建立這個目錄:

sudo mkdir /usbdisk

這個時候 USB 隨身碟應該還是掛載在 /media/pi/ 這個使用者層級的位置上,先把它卸載(從桌面環境的圖形界面應該就有這個功能)。

接著再以系統層級的方式,重新把這個 USB 隨身碟依據 /etc/fstab 的設定掛載:

mount -a

df 確認是否有正常掛載:

df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  7.2G  6.9G  51% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M   30M  433M   7% /dev/shm
tmpfs           463M  6.4M  457M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1   63M   21M   43M  34% /boot
/dev/sda1        29G  7.9G   20G  29% /usbdisk
tmpfs            93M     0   93M   0% /run/user/1000

這裡的倒數第二行就是新掛載的 USB 隨身碟,這樣就完成新增 USB 隨身碟的步驟了。

由於我們是將這個 USB 隨身碟寫在 /etc/fstab 中讓系統自動掛載,所以設定好之後,這個 USB 隨身碟就不要拔下來了,如果要拔的話,記得要把 /etc/fstab 的設定先調整一下,以免開機或自動掛載時找不到 USB 隨身碟。

設定 Swap 交換空間檔案位置

掛載一個外部的 USB 隨身碟之後,就可以將 swap 交換空間的檔案放在這上面了。設定的方式很簡單,只要修改 /etc/dphys-swapfile 這個設定檔的 CONF_SWAPFILE 參數即可:

# where we want the swapfile to be, this is the default
#CONF_SWAPFILE=/var/swap
CONF_SWAPFILE=/usbdisk/swap

CONF_SWAPFILE 是設定 swap 檔案放置的路徑,預設是 /var/swap,我們只要把它改為 USB 隨身碟的路徑之下(以我的例子來說就是 /usbdisk/ 之下),就可以讓 swap 檔案放在 USB 隨身碟中了,至於檔案名稱要取什麼都可以。

最後重新啟動 dphys-swapfile 服務:

service dphys-swapfile restart

檢查一下 swap 的狀態:

swapon -s
Filename                                Type            Size    Used    Priority
/var/swap                               file            1914876 0       -1
/usbdisk/swap                           file            1914876 0       -2

這時候可能會出現兩個 swap 交換空間,/var/swap 是舊的設定,這個空間在下一次重新開機之後,就不會被掛載了,未來只有 /usbdisk/swap 這個新的 swap 空間會被使用。

如果想要馬上把就的 swap 檔案清乾淨,可以將 /var/swap 這個 swap 空間手動關閉:

sudo swapoff /var/swap

然後再把這個檔案刪掉,節省空間:

sudo rm /var/swap

這樣就完成 USB 隨身碟上的 swap 交換空間設定了。

除了使用 ext4 檔案系統配合 swap 交換空間檔案的方式之外,亦可直接將 USB 隨身碟格式化為 swap 檔案系統,不過我個人是比較喜歡使用 ext4 的方式,因為這樣可以很方便的動態調整 swap 檔案的大小,剩下的空間還可以用來儲存自己的資料,使用上比較彈性。

參考資料:StackExchange