Rust
no_std runtime
no_std için minimal bir runtime yazarsın.
Bitirme görevi: no_std runtime
Gömülü sistemlerde işletim sistemi yoktur; görevleri çalıştıran küçük bir runtime'ı kendin yazarsın. Heap olmadan çalışabilmesi için görevler sabit kapasiteli bir dizide, fonksiyon işaretçisi olarak tutulur:
struct Calistirici {
gorevler: [Option<fn() -> u32>; 4],
adet: usize,
}
impl Calistirici {
const fn new() -> Self {
Self { gorevler: [None; 4], adet: 0 }
}
fn ekle(&mut self, g: fn() -> u32) -> Result<(), &'static str> {
let yer = self.gorevler.get_mut(self.adet).ok_or("kuyruk dolu")?;
*yer = Some(g);
self.adet += 1;
Ok(())
}
}
const fn new, çalıştırıcının static olarak derleme anında kurulabilmesini sağlar.
Görevleri çalıştırmak
Çalıştırıcı kuyruktaki görevleri sırayla çağırır ve sonuçlarını toplar. Gerçek bir gömülü runtime'da (embassy gibi) görevler async'tir ve kesmelerle (interrupt) uyandırılır; temel fikir aynıdır:
impl Calistirici {
fn hepsini_calistir(&self) -> u32 {
self.gorevler.iter().flatten().map(|g| g()).sum()
}
}
flatten, Option'lardan yalnızca Some olanları geçirir.
Uygulama Küçük runtime
Yukarıdaki Calistirici türünü new, ekle ve hepsini_calistir ile yaz. 1, 2 ve 3 döndüren üç görev ekle; N görev, toplam X yazdır.
Örnek çözümü göster
struct Calistirici {
gorevler: [Option<fn() -> u32>; 4],
adet: usize,
}
impl Calistirici {
const fn new() -> Self {
Self { gorevler: [None; 4], adet: 0 }
}
fn ekle(&mut self, g: fn() -> u32) -> Result<(), &'static str> {
let yer = self.gorevler.get_mut(self.adet).ok_or("kuyruk dolu")?;
*yer = Some(g);
self.adet += 1;
Ok(())
}
fn hepsini_calistir(&self) -> u32 {
self.gorevler.iter().flatten().map(|g| g()).sum()
}
}
fn bir() -> u32 {
1
}
fn iki() -> u32 {
2
}
fn uc() -> u32 {
3
}
fn main() {
let mut c = Calistirici::new();
for g in [bir as fn() -> u32, iki, uc] {
c.ekle(g).unwrap();
}
println!("{} görev, toplam {}", c.adet, c.hepsini_calistir());
}
Kendini test et
-
Neden closure yerine <code>fn() -> u32</code> işaretçisi kullanıldı?
- Daha okunaklıdır
- Neden yok
- Boyutu sabittir ve heap ya da Box gerektirmez
- Closure'lar no_std'de yoktur
Cevabı göster
Boyutu sabittir ve heap ya da Box gerektirmez — Farklı closure türlerini tek dizide tutmak Box<dyn Fn> ister; yakalamasız fonksiyon işaretçisi bunu heap olmadan çözer.
-
Boşları atla
self.gorevler.iter().____().map(|g| g()).sum()
Cevabı göster
self.gorevler.iter().flatten().map(|g| g()).sum()
-
Parça ve rolü
- [Option<fn() -> u32>; 4]
- Sabit kuyruk
- const fn new
- Derleme anı kurulum
- get_mut(adet)
- Kapasite denetimi
- flatten
- Boş yerleri atlar
Sıradaki ders: Profilli optimizasyon