[Rust] zerocopy
zerocopy๋ ๋ณต์ฌ๋น์ฉ ์๋ ๋ฉ๋ชจ๋ฆฌ ์กฐ์์ ๊ฐํธํ ํํ๋ก ๋ณด์กฐํ๋ crate๋ค.
๊ตฌ๊ธ์ด ํธํฌ์์ ์ ์์ ์ฐ๋ ค๊ณ ๋ง๋ ๊ฑธ๋ก ์๊ณ ์๋ค.
์ ํ์ํ๊ฐ?
zero-copy ๋ฐฉ๋ฒ๋ก ์ ๋ํ ๋ฐฑ๊ทธ๋ผ์ด๋๋ ๋ณ๋ ํฌ์คํธ๋ฅผ ์ฐธ์กฐํ๋ค.
https://blog.naver.com/sssang97/223629674161
์๋ฌดํผ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์์ ๋ค๊ณ ์จ ๋ฐ์ดํธ์ด ๋ฐ์ดํฐ๋ฅผ Rust์์ ์ ๋๋ก ๋ค๋ฃจ๋ ค๋ฉด ์ญ์ง๋ ฌํ/์ง๋ ฌํ๋ฅผ ๊ฑฐ์ณ์ struct/enum์ ํตํด ๊ฐ๊ณตํ๋๊ฒ ์ฃผ๋ ์ฌ์ฉ ํจํด์ผ ๊ฒ์ด๋ค.
๊ทผ๋ฐ ๊ทธ๋ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ ์ง๋ ฌํ์ ์ญ์ง๋ ฌํ๋ฅผ ๋ฐ๋ณตํ๋ฉด ํ์ ๋ถํ์ํ ๋ณต์ฌ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค.
์ด crate๋ ๋ณต์ฌ๊ฐ ๋ฐ์ํ์ง ์๋ ํํ์ unsafe ์ง๋ ฌํ/์ญ์ง๋ ฌํ๋ฅผ ์ ์ ํ๊ฒ ๊ฐ์ธ์ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
์ด๊ฒ ์์ฒด๋ก syscall๋ค์ ์ ๊ณตํ๋ ๊ฒ์ ์๋๋ค. ๋ณด์กฐ์ ์ธ ์ฉ๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ฐ์ zerocopy ์ข ์์ฑ์ ์ ์ ํ ์ถ๊ฐํด์ค๋ค.
derive๋ features๋ก ๋ฃ๋ ๋์ ์ zerocopy-derive๋ฅผ ๋ฐ๋ก ๋ฃ์ ์๋ ์๋ค.
๊ทธ๋ฌ๋ฉด ์ปดํ์ผ ์๋๊ฐ ๋์์ง๋ค๋...
์๋ฌดํผ, zerocopy๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ณดํต ์ด๋ฐ ๋๋์ผ๋ก ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ธํด์ ์ฌ์ฉํ๊ฒ ๋๋ค.
์ค์ง์ ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ํธ๋ ์์ ์ด 4๊ฐ์ง๋ค.
- TryFromBytes
- FromBytes
- IntoBytes
- FromZeros
TryFromBytes/FromBytes๋ ์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ์๊ณ ์๋ TryFrom ํจํด์ผ๋ก ๋ฐ์ดํธ์ด์ ๊ตฌ์กฐ์ฒด ๋ฑ์ผ๋ก ๋ณํํ๋ค. ๋ฐํ ํ์
์ Result<&T, Err>๋ค.
owned๊ฐ ์๋ ์ฐธ์กฐํ์ผ๋ก ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋ณต์ฌ ๋์์ ์ต์ํํ ์ฑ๋ก ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
IntoBytes๋ ๊ฐ๋จํ๋ค. ๊ตฌ์กฐ์ฒด ๋ฑ์ ๋ฐ์ดํธ์ด๋ก ๋ณํํ๋ ๊ฒ์ด๋ค.
FromZeros๋ ์ข ํน์ดํ๋ฐ, ๊ฐ์ฒด๊ฐ ๊ธฐ๋ณธ๊ฐ(0)์ธ ์ํ๊ฐ ์ ํจํ ์ํ์์ ๋ณด์ฅํ๋ trait์ด๋ค.
๋ zero-copy์๋ zerocopy ๊ตฌํ์ ํ์ํ ๋ณด์ฅ์ ๋ํ๋ด๋ ๋ง์ปค trait์ด 3๊ฐ์ง ์๋ค. ์๋ ๋ง์ปค๋ค์ ์ ์ ํ ๋ฌ์์ค์ผ ์์ ๊ธฐ๋ฅ derive๋ ๋ฌ์ฑํ ์ ์๋ค.
- KnownLayout
- Immutable
- Unaligned
KnownLayout๋ ๋๋ถ๋ถ์ zerocopy ์ฌ์ฉ์ฌ๋ก์ ํ์ํ ๊ธฐ๋ณธ ๋ง์ปค๋ค. ์ด๊ฑธ ๋ฌ์๋์ผ ์ค์ ๊ตฌ์กฐ์ฒด์ ๋ ์ด์์ ๋ถ์์ ๊ตฌํํด์ค ์ ์๋ค.
Immutable๋ ํด๋น ํ์
์ด ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํด์ผํจ์ ๋ปํ๋ค.
Unaligned๋ ๋ฉ๋ชจ๋ฆฌ alignment๊ฐ ํ์ํ์ง ์๋ ํ์
์ ๊ฐ๋ฆฌํจ๋ค.
์ผ๋จ ํ๋ฒ ์ค์ ๋ก ๋ง๋ค์ด๋ณด์.
use zerocopy::*;
#[derive(Debug, KnownLayout, Immutable, TryFromBytes)]
#[repr(u32)]
enum Cuppa {
Tea { iced: bool, milk: u8 } = u32::from_ne_bytes(*b"CHAI"),
Coco { marshmallows: u8 } = u32::from_ne_bytes(*b"COCO"),
}
๊ตฌ์กฐ์ฒด ํ๋๋ฅผ zerocopy๋ฅผ ๋์ง๋์ง ๋ฌ๋ฉด์ ๋ง๋ค์๋ค.
enum์ ๊ฐ์ ํ ๋นํ๊ฑด ๋ณ ์๋ฏธ๋ ์๋ค. ๊ทธ๋ฅ ํ๊ฑฐ๊ณ , ๊ผญ ์ ๋์ผ ํ ํ์๋ ์๋ค.
์ด ๊ฒฝ์ฐ์ TryFromBytes๋ฅผ ๋ฌ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํธ์ด->๊ตฌ์กฐ์ฒด ๋ณํ์ ์ฌ์ฉํ ์ ์๋ค.
๊ทธ๋ผ ์ด๋ฐ ๋๋์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.

let data = u64::from_ne_bytes([b'C', b'H', b'A', b'I', 1, 42, 0, 0]);
let obj = Cuppa::try_ref_from_bytes(data.as_bytes());
if let Ok(Cuppa::Tea { iced, milk }) = obj {
println!("iced: {}, milk: {}", iced, milk);
}
๋ฐ์ดํธ์ด์ ๋ฐ์์, ๊ทธ๊ฑธ ๋ณํํ๊ณ ์ถ๋ ฅํ๋๋ก ํ๋ค.
๊ทธ๋ผ ์ ๋์ํ ๊ฒ์ด๋ค.
์์ ๋งํ๋ฏ์ด ์ ๊ธฐ์ ์์ฑ๋ obj ๊ฐ์ฒด๋ ์ฐธ์กฐ๋ ์ฑ๋ก ๊ตฌ์กฐ์ฒด ๋ชจ์์ ๊ฐ์ถ ๊ฒ์ผ ๋ฟ์ด๋ค.
๊ทธ๋์ ์ค์ ๋ก๋ ๋ณต์ฌ๋ ๊ฒ์ด ์๋๋ผ ์ฐธ์กฐ๋ ๊ฒ์ด๋ค.
์ด๊ฑฐ ๋ง๊ณ ๋ ๋ฐ์ดํธ์ด ์ญ๋ณํ์ด๋ ์์ํ ๋ณด์กฐ๊ธฐ๋ฅ๋ค์ด ์๊ธด ํ์ง๋ง, ์ด๊ฒ zero-copy๋ผ๋ crate์ ํต์ฌ์ด๋ค.
https://github.com/google/zerocopy/discussions/1680
https://google.github.io/comprehensive-rust/ko/bare-metal/useful-crates/zerocopy.html
https://github.com/google/zerocopy/discussions/1680