CodeBlanks Logo Icon CodeBlanks

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.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
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());
}

Beklenen çıktı

3 görev, toplam 6

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Neden closure yerine <code>fn() -&gt; u32</code> işaretçisi kullanıldı?

  • Daha okunaklıdır
  • Neden yok
  • Boyutu sabittir ve heap ya da Box gerektirmez Doğru cevap
  • Closure'lar no_std'de yoktur

Açıklama: Farklı closure türlerini tek dizide tutmak Box<dyn Fn> ister; yakalamasız fonksiyon işaretçisi bunu heap olmadan çözer.

2 Boşları atla

Soru
self.gorevler.iter().____().map(|g| g()).sum()
Cevap
self.gorevler.iter().flatten().map(|g| g()).sum()

Açıklama: Option yineleyicisinde flatten yalnızca Some değerleri verir.

3 Parça ve rolü

Kavram Anlamı
[Option<fn() -> u32>; 4] Sabit kuyruk
const fn new Derleme anı kurulum
get_mut(adet) Kapasite denetimi
flatten Boş yerleri atlar

Uzman bölümündeki tüm dersler