(More Info) |
The Raspberry Pi (and most other small form factor Linux computers on a board like Beaglebone and C.H.I.P) have a common issue when used as a headless embedded system: Powering down!
The operating system wants to write to the drive (in this case, the FLASH memory) for a number of reasons like saving log files or updating access time stamps on files. Not only over time the FLASH memory may get damaged. FLASH chips have a finite number of write/erase cycle before they stop working. Maybe even worse, if you lose power while one of these operations is going on, you can corrupt the drive and make the system unusable, otherwise referred to as "bricked". It is actually worse on FLASH drives than on old fashionned spinning platter hard drives because when saving to FLASH, entire sectors of the FLASH memory have to be copied to RAM, modified and saved back to FLASH and a sector can contain information about more than one file, so losing a sector on a FLASH drive can be quite detrimental to the entire filesystem and is usually not recoverable.
One way to avoid this is to run entirely from RAM disk. the process goes as follows:
The advantage of that is that FLASH is only used initially then it can be made invisible from the OS while running and any risk of corruption is totally eliminated. Since RAM is usually quite a bit faster than FLASH, the system is also much faster.
The main inconvenients are that any change is temporary and is lost when power is removed, so if you actually want to make permanent changes, the process can be fairly involved (remount the FLASH drive and make your changes there.) Another issue with that approach is that it uses a lot of RAM so it may be more suitable for small systems.
An option is to mount the FLASH drive read-only. The OS will still run from FLASH but there will nbe no risk of corruption. When you need to mke changes to the configuration, you can momentarily reboot with the OS partition read-write.
Here is a good web page describing the process:
http://hallard.me/raspberry-pi-read-only/
Another alternative is to create a RAM disk only for these folders where the chip needs to write during operation and turn off the time stamp update feature of the OS so that under normal conditions, the OS never needs to write to the folders hosting the actual operating system files.
This leaves you the option of making changes to the OS configuration when you need to (and assuming that when you do that, you make sure that power is not removed while doing it) but any temporary files like log files are saved to RAM disk and may be lost when power is removed. These files are not essential to make sure the chip can boot when power is restored, so nothing important is lost and the FLASH drive is not corrupted if power is removed abruptly.
I found this web page that describes the process in some details:
https://www.zdnet.com/article/raspberry-pi-extending-the-life-of-the-sd-card/
Just in case the page would disappear, I have copied the important bits below:
As mentioned earlier in the article, tmpfs can write to RAM instead of the local disk (in this case, the SD card). Using it is simple. All that needs to be done is add an entry to the /etc/fstab file (to mount the folder you wish to have written to RAM) and reboot (so that each mount is cleanly mounted before services start writing files).
The kernel will do the rest for you by managing the writes to the RAM on this virtual filesystem. The really neat part about this is that the kernel will only use the amount of RAM required for writing files, not the entire size of the mount. So, for example, say we add this line to the /etc/fstab file:
tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=0755,size=100m 0 0
The kernel will mount /var/log to RAM, however it will not use any RAM until files are written to /var/log. When files are written to /var/log, the kernel will save them to RAM and only use space to save the files. When files are removed from /var/log, the associated RAM to store them is freed up.
This means that it only uses what RAM it needs to in order to store the files, which makes it very efficient.
In /etc/fstab, you can also specify the total size to allocate for each mount. In the example above, we set "size=100m" so that /var/log can use up to 100 MB of space and no more. This avoids a filesystem from using up all of the RAM which can cause the system to slow down or even crash. By running the "mount" command, we can see in the example above that /var/log is mounted as a tmpfs volume to RAM, 100 MB in size.
Filesystem Size Used Avail Use% Mounted on
tmpfs 100M 596K 100M 1% /var/log
There are a variety of locations that GNU/Linux likes to make frequent writes. This is a list of entries below that I use as a starting point that should fit for most distributions.
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=100m 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=30m 0 0
tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=0755,size=100m 0 0
tmpfs /var/run tmpfs defaults,noatime,nosuid,mode=0755,size=2m 0 0
tmpfs /var/spool/mqueue tmpfs defaults,noatime,nosuid,mode=0700,gid=12,size=30m 0 0
As you can see I make use of the "size=" parameter to avoid using up huge amounts of RAM in case something tries to save a huge amount of data. The "noatime" and "nosuid" parameters are also recommended for security and performance, and "mode=" along with "gid=" matches the permissions and group of the original filesystem to what was located on the SD card originally.
Yep, tmpfs can also handle permissions. As usual, entries in /etc/fstab mount over the top of what is on the SD card, as standard Unix/Linux types do. So if for some reason the mounts fail, writes will still work to the SD card.
One additional point to keep in mind is that anything mounted with tmpfs will be lost on a reboot. So, logs in /var/log in the example above will be wiped out if the computer is shut down or rebooted. So you will not want to save any files with tmpfs that need to be persistent among reboots.
Here are useful tips for the C.H.I.P. small Linux computer board that used to sell for $9.00: