💻

【Raspberry Pi】RAMディスク化したSDカードに書き込み可能な領域を作る

に公開

はじめに

現在、Raspberry Piをベースとした、新しい監視カメラシステムを開発中ですが、そこで利用している様々な技術的なトピックをメモ代わりにまとめていきたいと思います。

今回は、RAMディスク化したRaspberry PiのSDカードに書き込み可能な領域を作る方法です。

※RAMディスク化の方法についてはこちらの記事を参照してください
https://zenn.dev/daddy_yukio/articles/a722e6c024efaf

概要

Raspberry Piを使用して、IoTデバイスを開発し、実運用していく為に必要なRAMディスク化ですが、実際に開発していくと、アプリの設定値などを書き込む必要が出てくる場面が多くあります。

設定を変更する必要が出てくるたびに、RAMディスク化を解除->設定を変更->RAMディスク化を有効、という手順を踏むのは面倒です。

設定ファイルの変更は頻繁に行われるわけではなく、基本的には読み込み処理のみですので、SDカードの劣化に大きな影響は与えないと思われます。

そこで、書き込み処理の少ない設定の保存等のために、書き込み可能な領域を作る方法を説明します。

必要な環境

SDカードに焼いたRaspberry Pi OSのext4フォーマットのボリュームを作成したり、サイズを変更したりします。
そのため、UbuntuなどのLinux環境が必要です。
また、SDカードをマウントできるデバイス(SDカードリーダー・ライター)も併せて必要になります。

Windows上でSDカードリーダー・ライターが認識できていれば、VirtualBoxなどの仮想環境上からもSDカードをマウントすることが可能です。

ここでは、Ubuntu24.04での作業について記載していきます。

手順

ここではRaspberry Pi OS Lite (64bit)を使用して、ルート配下をRAMディスク化したまま、/home配下のみを書き込み可能な状態にしていきます。

まずはRaspberry Pi OSをSDカードに焼きます。

OSをSDカードに焼いた後、一度Raspberry Piに差して起動してください。マウント情報など、初期設定が走ります。

この時のディスク情報は以下のようになっています。

初期状態
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.6G     0  1.6G   0% /dev
tmpfs           380M  6.5M  373M   2% /run
/dev/mmcblk0p2  117G  2.1G  109G   2% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M   16K  5.0M   1% /run/lock
/dev/mmcblk0p1  510M   66M  445M  13% /boot/firmware
tmpfs           380M     0  380M   0% /run/user/1000

その後、Shutdownしてから、SDカードをRaspberry Piから抜いて、Ubuntuに差してください。
自動でマウントされるはずです。

その後、ディスクユーティリティを起動します。

下記は128GBのSDカードにRaspberry Pi OSを焼いた状態の情報です。

パーティション(ボリューム)が2つ存在していると思います。
一つはブート領域(bootfs)で、もう一つがルート領域(rootfs)です。

それでは、作業を進めていきます。
作業手順は以下です。

  1. rootfsボリュームのサイズを縮小する
  2. homeボリュームを新たに作成する
  3. 現状の/homeをコピー
  4. 新たに作成したhomeボリュームをマウント
  5. RAMディスク化する

1. rootfsボリュームのサイズを縮小する

まず最初に、rootfsボリュームのサイズを縮小させ、新たに作るhomeボリュームの領域を確保します。

ディスクユーティリティ上で、rootfsボリュームを選択して、左下のカギマークをクリックすると、メニューが表示されます。
このメニューから「サイズを変更」を選択すると、「ボリュームのサイズを変更」画面が開きます。

初期状態では、SDカードの容量一杯にrootfsボリュームが作成されていますが、このサイズを縮小します。

home領域として必要なサイズ分、減少させたサイズを指定したら、「サイズを変更」ボタンを押します。

サイズ変更には少し時間がかかりますので、処理が終わるまで、そのまま待ちます。

成功すると、新たに「空き領域」が作成されます。

2. homeボリュームを新たに作成する

新たに作成された空き領域に、homeボリュームを作成していきます。

空き領域を選択した状態で、左下の「+」ボタンを押すと「パーティションを作成」画面が表示されます。
デフォルトで、選択した空き領域のサイズが入っていますので、問題なければそのまま「次へ」を押すと、「ボリュームを初期化」画面が表示されます。

ここでは「ボリューム名」に「home」と入力し、「タイプ」を「Linux用の内臓ディスクとして使用する(Ext4)」を選択してください。

「作成」ボタンを押すと、入力された容量のパーティションが作成され、その領域にext4フォーマットのhomeボリュームが作成されます。

homeボリュームが作成されたら、Ubuntuでの作業は終了です。
SDカードを取り出してください。

3. 現状の/homeをコピー

homeボリュームを作成したSDカードを、再度Raspberry Piに差して起動します。

この状態では新たに作成したhomeボリュームのマウント情報がありませんので、自動的にマウントはされません。

まずは、ディスクの情報をblkidコマンドで確認します。

blkidでディスクの情報を確認する
$ sudo blkid
/dev/mmcblk0p3: LABEL="home" UUID="xxxxxxx" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="abcdef-03"
/dev/mmcblk0p1: LABEL_FATBOOT="bootfs" LABEL="bootfs" UUID="xxxxxx" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="abcdef-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="xxxxxxxx" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="abcdef-02"

最初から作成されていた2つのパーティション(/dev/mmcblk0p1, /dev/mmcblk0p2)の他に、新たに作成したhome用のパーティション(/dev/mmcblk0p3)の情報が表示されると思います。

この情報のPARTUUIDの値をコピーしておきます。

まず、作成したhome領域を一時的にマウントして、現状の/home配下の情報をコピーします。

一時的にマウントして情報をコピー
sudo mkdir /mnt/newhome
sudo mount /dev/mmcblk0p3 /mnt/newhome
sudo rsync -aXS --progress /home/ /mnt/newhome/

コピーが終わったら、念のため現状の/homeをバックアップした後、新たに空の/homeを作成します。

現状の/homeをバックアップ
sudo mv /home /home.back
sudo mkdir /home

4. 新たに作成したhomeパーティションをマウント

作成した空の/homeに、SDカード上に作成したhomeボリュームをマウントさせます。

OS起動時のディスクマウント情報を記述する/etc/fstabファイルを開きます。

/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=abcdef-01  /boot/firmware  vfat    defaults          0       2
PARTUUID=abcdef-02  /               ext4    defaults,noatime  0       1

最初からマウントされている2つのパーティションの情報が記載されていますので、その下に、新しく作成したhome用のパーティションを/homeにマウントするように、下記の1行を加えます。

/homeのマウント情報
PARTUUID=abcdef-03  /home  ext4  defaults  0 2

PARTUUIDは、先ほどblkidコマンドで確認した値を設定します。

これを保存して、Raspberry Piを再起動します。

再起動後、dfコマンドで確認します。

dfコマンドでマウント状況を確認
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.6G     0  1.6G   0% /dev
tmpfs           380M  5.9M  374M   2% /run
/dev/mmcblk0p2   71G  2.2G   65G   4% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M   16K  5.0M   1% /run/lock
/dev/mmcblk0p3   46G   52K   44G   1% /home
/dev/mmcblk0p1  510M   67M  444M  14% /boot/firmware
tmpfs           380M     0  380M   0% /run/user/1000

/homeに、新しく作成したパーティション領域がマウントされていて、容量が作成した容量になっていればOKです。

バックアップしておいた/home.backは削除しておきます。

/home.backを削除
sudo rm -r /home.back

5. RAMディスク化する

この状態で、一旦、raspi-configを使用して、ルート配下をRAMディスク化します。
その際、ブートパーティションは書き込み可能の状態にしておいてください。

再起動後、dfコマンドで状態を確認すると、下記のように/homeもro(Read-Only)の/media/root-ro/homeにマウントされています。

dfで状態確認
$ df -h
Filesystem           Size  Used Avail Use% Mounted on
udev                 1.6G     0  1.6G   0% /dev
tmpfs                380M  5.9M  374M   2% /run
/dev/mmcblk0p2        71G  2.2G   65G   4% /media/root-ro
tmpfs-root           1.9G   48K  1.9G   1% /media/root-rw
overlayroot          1.9G   48K  1.9G   1% /
tmpfs                1.9G     0  1.9G   0% /dev/shm
tmpfs                5.0M   16K  5.0M   1% /run/lock
/dev/mmcblk0p1       510M   59M  452M  12% /boot/firmware
/dev/mmcblk0p3        46G   56K   44G   1% /media/root-ro/home
/media/root-ro/home  1.9G   48K  1.9G   1% /home
tmpfs                380M     0  380M   0% /run/user/1000

これは、raspi-configで実行するoverlayFS(厳密にはoverlayroot)では、ルート配下にサブマウントされた領域も含めて、すべてRAMディスク化する設定になっています。

この設定を「サブマウントされた領域は何もしない」という設定に変更する必要があります。

この設定は、ブート領域にある下記のファイルで行います。

/boot/firmware/cmdline.txt

上記のファイルを開くと、下記のような1行のコマンドが記述されています。

変更前
overlayroot=tmpfs console=serial0,115200 console=tty1 root=PARTUUID=abcdef-02 rootfstype=ext4 fsck.repair=yes rootwait

この先頭の「overlayroot=tmpfs」に引数を追加して、「overlayroot=tmpfs :recurse=0 」と変更します。

変更後
overlayroot=tmpfs:recurse=0 console=serial0,115200 console=tty1 root=PARTUUID=abcdef-02 rootfstype=ext4 fsck.repair=yes rootwait

変更したら再起動して、dfコマンドで確認します。

dfコマンドで確認
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.6G     0  1.6G   0% /dev
tmpfs           380M  5.9M  374M   2% /run
/dev/mmcblk0p2   71G  2.2G   65G   4% /media/root-ro
tmpfs-root      1.9G   48K  1.9G   1% /media/root-rw
overlayroot     1.9G   48K  1.9G   1% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M   16K  5.0M   1% /run/lock
/dev/mmcblk0p1  510M   59M  452M  12% /boot/firmware
/dev/mmcblk0p3   46G   56K   44G   1% /home
tmpfs           380M     0  380M   0% /run/user/1000

/homeが直接SDカード上のパーティションにマウントされていればOKです。

RAMディスク化の有効化/無効化

これで、ルート配下はRAMディスク化した状態で、/home配下は書き込みが可能になりました。

ただ、この設定を行うと、RAMディスク化の有効化/無効化にraspi-configを使うことができません。
(/homeも一緒にRAMディスク化されてしまうので)

ただ、1度raspi-configでRAMディスク化を実行していれば、必要なモジュール等のインストールは完了していますので、以後は、/boot/firmware/cmdline.txtを編集するだけで、RAMディスク化の有効/無効を切り替えられます。

  • 有効にする場合
    • コマンドの先頭に「overlayroot=tmpfs:recurse=0」を追加
  • 無効にする場合
    • コマンドの先頭の「overlayroot=tmpfs:recurse=0」を削除

上記の処理を行うシェルスクリプトを用意しておけば、楽に切り替えられるようになります。

最後に

これでRaspberry PiのSDカードをRAMディスク化しつつ、/homeだけは書き込み可能にすることができました。

ちなみに、こんな感じのものを開発中です。

このシステムで使用している技術の概要は以下のBookにまとめていますので、ご興味のある方は読んでみてください。
https://zenn.dev/daddy_yukio?tab=books
また、近日中にテスターの募集を行う予定ですので、お手伝いしていただける方はよろしくお願いします。
(後日、どこかで募集します。。。)

Discussion