14.3.3. Dosya sistemi hijyeni¶
Sevk edilen bir kameradaki flash bellek ve SD depolama, hiçbir operatörün elle temizlemeyeceği dosyalarla dolar. Bu depolamayla ilgili iki karar, ürünün ömrü boyunca onunla birlikte kalır: hangi yüzeyin hangi tür veriyi tutacağı ve uygulama kayıtları biriktirdikçe dosya işlemlerinin çalışmaya devam edebilmesi için dizinlerin nasıl yapılandırıldığı.
14.3.3.1. Neyin nereye gideceği¶
Kod ve varlıklar, derlemenin sevk zamanında işlediği donmuş modüllerde ve ROMFS içinde taşınır. Uygulama durumu – uygulamanın çalışma zamanında yazdığı her şey, büyüyen her şey, önyüklemeler arasında değişen her şey – başka bir yerde bulunmak zorundadır. Kamera bunun için iki yazılabilir yüzey sunar:
/flashkonumundaki dahili flash bellek: herhangi bir uygulama kodu çalışmadan önce bağlanan küçük, yazılabilir bir dosya sistemi. Yeniden başlatmalardan sağ çıkan küçük, sabit boyutlu kayıtlar için doğru yer: uygulamanın çalışma zamanında güncellediği yapılandırma, bilinen son kalibrasyon, sürekli artan bir sayaç, “bu kamera hazırlandı” diyen tek satırlık bir işaret dosyası. Sınırlı yazma döngüleri – modern dahili flash bellek, sektör başına milyonlarca değil binlerce ila on binlerce yazmaya dayanır; bu nedenle yazma işlemleri çerçeve başına değil, seyrek olmalıdır./sdcardkonumundaki SD kart: bir kart mevcut olduğunda bağlanan daha büyük, yazılabilir bir dosya sistemi. Hacimli, değişken dosyalar için doğru yer: görüntü ve video yakalamaları, günlük dosyaları, model ince ayar verileri, megabaytlara veya gigabaytlara büyüyebilecek her şey. Dahili flash bellekten daha yüksek yazma kapasitesine sahiptir ancak yine de sonludur; çıkarılabilir, değiştirilebilir ve uygulama yazma işleminin ortasındayken kaybolması en muhtemel yüzeydir.
Bir şeyin nereye yazılacağı sorusunun doğru cevabı neredeyse her zaman “küçük sabit kayıtlar için flash bellek, geri kalan her şey için SD” şeklindedir. İkisi birbirinin yerine geçmez: sürekli artan günlük dosyasını /flash konumuna karalayan bir uygulama, SD üzerinde sorunsuz çalışacak bir kurulumda flash belleğin yazma dayanıklılığını tüketir.
14.3.3.2. Her ikisini de başarısız-olabilir olarak değerlendirin¶
/flash ve /sdcard her ikisi de başarısız olabilir. SD kart çıkarılabilir, flash bellek yazma sırasında bir güç kaybıyla bozulabilir, her ikisinin de yeri dolabilir ve her ikisi üzerindeki herhangi bir işlem, uygulamanın sahada teşhis etme şansını bulamayacağı nedenlerle OSError yükseltebilir.
İki desen, uygulamanın bundan sağ çıkmasını sağlar:
Bağlamaları ve işlemleri try bloklarına sarın. Kullanıcı veri yollarına karşı her
open(),os.listdir(),os.rename()çağrısı potansiyel olarak başarısız olur.OSErroryakalayın, günlüğe kaydedin ve tanımlı bir alternatife geri dönün –/sdcardyoksa/flashkonumuna yazın, hiçbiri yoksa işlemi atlayın.Bir güç kaybından sağ çıkması gereken dosyalar için atomik yazmalar. Geçici bir yola yazın, tutamacı kapatın, ardından canlı adın üzerine
os.rename()uygulayın. Ya yeniden adlandırma başarılı olur ve dosya yeni sürümdür, ya da olmaz ve dosya eski sürümdür. Dosyanın yarı yazılmış olduğu üçüncü bir durum yoktur:import os def write_config_atomic(path, contents): tmp = path + '.tmp' with open(tmp, 'w') as f: f.write(contents) f.flush() os.rename(tmp, path)
Desen hem flash bellekte hem de SD’de çalışır. Geçici dosyanın, dosya sisteminin boş alanını tükettiği kadar büyük dosyalar için çalışmaz; bunu küçük kayıtlar için ayırın.
14.3.3.3. Yavaş dizin tuzağı¶
MicroPython VFS, dizin içeriğini bir masaüstü dosya sisteminin yaptığı gibi indekslemez. os.listdir() ve os.stat(), altta yatan dosya tablosunu doğrusal olarak gezer. Yüz dosyalı bir dizin sorunsuzdur; on bin dosyalı bir dizin kullanılamayacak kadar yavaştır; her os.listdir() saniyeler sürer ve her open() geçişi sırasında tabloya karşı kontrol yapar.
Disk’e günlük veya yakalama yazan uygulamalar buna en hızlı şekilde takılır. Dakikada bir yeni dosya açan naif bir /sdcard/logs/<timestamp>.log şeması, bir yıllık kurulumda logs/ dizinini yarım milyon dosyayla doldurur. Bundan çok önce uygulama, her dosya açma işlemi bir çerçeve aralığından daha uzun sürdüğü için çerçeve hızını kaçırmaya başlar.
Doğru desen, dosyaları tarihlendirilmiş alt dizinlerden oluşan bir ağaca bölmektir; böylece hiçbir tek dizin asla birkaç yüz girişten fazlasını tutmaz:
import os
import time
LOG_ROOT = '/sdcard/logs'
def log_path(now=None):
if now is None:
now = time.localtime()
year, month, day, hour = now[0], now[1], now[2], now[3]
directory = '{}/{:04d}/{:02d}/{:02d}'.format(
LOG_ROOT, year, month, day)
_makedirs(directory)
return '{}/{:02d}.log'.format(directory, hour)
def _makedirs(path):
# os.makedirs equivalent -- create each level if missing
parts = path.split('/')
for i in range(2, len(parts) + 1):
sub = '/'.join(parts[:i])
try:
os.mkdir(sub)
except OSError:
pass
Saatte bir dosya tutulan bir yıllık günlük kaydı artık 365 gün dizinine yayılır ve her biri en fazla 24 dosya içerir; herhangi bir dizine karşı os.listdir() ucuz kalır ve uygulamanın çerçeve döngüsü kurulum yaşlandıkça dosya işlemlerinde takılmaz.
Aynı ilke görüntü yakalamalarına, sensör izlerine veya uygulamanın olay başına bir dosya yazdığı başka her şeye uygulanır. Olay hızı yüksekse, ağacın daha derin olması istenir (yıl/ay/gün/saat veya yıl/ay/gün/saat/dakika); böylece her yaprak dizin küçük kalır. Olay hızı düşükse, bir yıl/ay ağacı yeterlidir.
14.3.3.4. Cihaz başına yollar¶
Birden fazla kameradan oluşan bir filoda, günlük dosyalarının hangi fiziksel birimden geldiklerini tanımlamaları gerekir. machine.unique_id(), kameraya fabrikada işlenmiş bir donanım tanımlayıcısı döndürür; bu değer yeniden başlatmalar, aygıt yazılımı güncellemeleri ve SD kart değişimleri arasında aynıdır. Bunu günlük yoluna veya günlük kayıtlarına gömün, böylece bir yığın SD karta veya merkezi bir günlüğe bakan bir operatör hangisinin hangisi olduğunu söyleyebilir:
import binascii
import machine
UNIT_ID = binascii.hexlify(machine.unique_id()).decode()
LOG_ROOT = '/sdcard/logs/' + UNIT_ID
Tarihlendirilmiş alt dizin deseniyle birleştirildiğinde, düzen /sdcard/logs/<unit-id>/2026/06/09/14.log halini alır – bir birimin bir saatlik kayıtları, gezilemeyecek kadar sığ bir dizinde, dosya sisteminin kendisi üzerinde birimi adlandıran bir yolda.
14.3.3.5. Hepsini bir araya getirmek¶
Sevk edilen bir kameranın yazılabilir depolaması kabaca şuna benzer:
/flash– yapılandırma, kalibrasyon, bir hazırlama işareti. Nadiren yazılır, sık okunur. Kaybı bir sonraki önyüklemeyi bozacak herhangi bir dosya için atomik-yeniden-adlandırma deseni./sdcard/logs/<unit-id>/<year>/<month>/<day>/<hour>.log– operasyonel günlük. Sürekli yazılır, yola göre döndürülür, asla binlerce kardeşi olan bir dizinden geçirilerek yazılmaz./sdcard/captures/<unit-id>/<year>/<month>/<day>/– uygulamanın yaptığı görüntü veya video yakalamaları. Aynı ağaç şekli, aynı neden.
Bu düzen uygulamaya yaklaşık yirmi satır kod maliyeti getirir ve onu, bir kurulumun aylar içinde kamerayı çökerten başarısızlık modlarından kurtarır.