zerocopy

FuchsiaํŒ€์ด ๋งŒ๋“  zerocopy ํฌ๋ ˆ์ดํŠธ๋Š” ๋ฐ”์ดํŠธ ์‹œํ€€์Šค๋ฅผ ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ ˆ์ž‡ ๋ฐ ๋งคํฌ๋กœ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

use zerocopy::AsBytes;

#[repr(u32)]
#[derive(AsBytes, Debug, Default)]
enum RequestType {
    #[default]
    In = 0,
    Out = 1,
    Flush = 4,
}

#[repr(C)]
#[derive(AsBytes, Debug, Default)]
struct VirtioBlockRequest {
    request_type: RequestType,
    reserved: u32,
    sector: u64,
}

fn main() {
    let request = VirtioBlockRequest {
        request_type: RequestType::Flush,
        sector: 42,
        ..Default::default()
    };

    assert_eq!(
        request.as_bytes(),
        &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]
    );
}

์ด ํฌ๋ ˆ์ดํŠธ๋Š” ํœ˜๋ฐœ์„ฑ(volatile) ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ MMIO์— ์ ํ•ฉํ•˜์ง€ ์•Š์ง€๋งŒ, ํ•˜๋“œ์›จ์–ด์™€ ๊ณต์œ ๋˜๊ฑฐ๋‚˜(์˜ˆ: DMA์—์„œ) ์™ธ์žฅ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ „์†ก๋˜๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐ์—๋Š” ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์–ด๋–ค ํƒ€์ž…์ด ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋ฐ”์ดํŠธ ํŒจํ„ด๋“ค์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ๊ฐ’์„ ๊ฐ€์งˆ ๋•Œ์—๋งŒ , ๊ทธ ํƒ€์ž…์ด FromBytes๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•ด์„œ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ๋ฐ”์ดํŠธ ์‹œํ€€์Šค๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ํ•ด๋‹น ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์œ„ ์ฝ”๋“œ์—์„œ ์ •์˜ํ•œ ํƒ€์ž…์— ๋Œ€ํ•ด FromBytes๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. RequestType์€ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  u32 ๊ฐ’์„ ์‹๋ณ„์ž๋กœ ๋ฐ›์•„๋“ค์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฆ‰ ๋ชจ๋“  ๋ฐ”์ดํŠธ ํŒจํ„ด์ด ์œ ํšจํ•œ RequestType๊ฐ’์€ ์•„๋‹™๋‹ˆ๋‹ค.
  • zerocopy::byteorder์—๋Š” ๋ฐ”์ดํŠธ ์˜ค๋”์— ๋”ฐ๋ฅธ ์„œ๋กœ ๋‹ค๋ฅธ ํ‘œํ˜„ ๋ฐฉ์‹์„ ์ง€์›ํ•˜๋Š” ์ˆซ์ž ํƒ€์ž…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • src/bare-metal/useful-crates/zerocopy-example/์—์„œ cargo run์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์‹œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค(์ข…์†์„ฑ ๋ฌธ์ œ๋กœ ์ธํ•ด ํ”Œ๋ ˆ์ด๊ทธ๋ผ์šด๋“œ์—์„œ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).