diff options
Diffstat (limited to 'book/ru/src/internals/access.md')
| -rw-r--r-- | book/ru/src/internals/access.md | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/book/ru/src/internals/access.md b/book/ru/src/internals/access.md new file mode 100644 index 0000000..ea073a4 --- /dev/null +++ b/book/ru/src/internals/access.md @@ -0,0 +1,158 @@ +# Контроль доступа + +Одна из основ RTIC - контроль доступа. Контроль того, какая часть программы +может получить доступ к какой статической переменной - инструмент обеспечения +безопасности памяти. + +Статические переменные используются для разделения состояний между обработчиками +прерываний, или между обработчиком прерывания и нижним контекстом выполнения, `main`. +В обычном Rust коде трудно обеспечить гранулированный контроль за тем, какие функции +могут получать доступ к статическим переменным, поскольку к статическим переменным +можно получить доступ из любой функции, находящейся в той же области видимости, +в которой они определены. Модули дают частичный контроль над доступом +к статическим переменным, но они недостаточно гибкие. + +Чтобы добиться полного контроля за тем, что задачи могут получить доступ +только к статическим переменным (ресурсам), которые им были указаны в RTIC атрибуте, +фреймворк RTIC производит трансформацию структуры кода. +Эта трансформация состоит из размещения ресурсов (статических переменных), определенных +пользователем *внутри* модуля, а пользовательского кода *вне* модуля. +Это делает невозможным обращение пользовательского кода к статическим переменным. + +Затем доступ к ресурсам предоставляется каждой задаче с помощью структуры `Resources`, +чьи поля соответствуют ресурсам, к которым получает доступ задача. +Есть лишь одна такая структура на задачу и структура `Resources` инициализируется +либо уникальной ссылкой (`&mut-`) на статическую переменную, либо с помощью прокси-ресурса (см. +раздел [критические секции](critical-sections.html)). + +Код ниже - пример разных трансформаций структуры кода, происходящих за сценой: + +``` rust +#[rtic::app(device = ..)] +mod app { + static mut X: u64: 0; + static mut Y: bool: 0; + + #[init(resources = [Y])] + fn init(c: init::Context) { + // .. пользовательский код .. + } + + #[interrupt(binds = UART0, resources = [X])] + fn foo(c: foo::Context) { + // .. пользовательский код .. + } + + #[interrupt(binds = UART1, resources = [X, Y])] + fn bar(c: bar::Context) { + // .. пользовательский код .. + } + + // .. +} +``` + +Фреймворк создает код, подобный этому: + +``` rust +fn init(c: init::Context) { + // .. пользовательский код .. +} + +fn foo(c: foo::Context) { + // .. пользовательский код .. +} + +fn bar(c: bar::Context) { + // .. пользовательский код .. +} + +// Публичное API +pub mod init { + pub struct Context<'a> { + pub resources: Resources<'a>, + // .. + } + + pub struct Resources<'a> { + pub Y: &'a mut bool, + } +} + +pub mod foo { + pub struct Context<'a> { + pub resources: Resources<'a>, + // .. + } + + pub struct Resources<'a> { + pub X: &'a mut u64, + } +} + +pub mod bar { + pub struct Context<'a> { + pub resources: Resources<'a>, + // .. + } + + pub struct Resources<'a> { + pub X: &'a mut u64, + pub Y: &'a mut bool, + } +} + +/// Детали реализации +mod app { + // все, что внутри этого модуля спрятано от пользовательского кода + + static mut X: u64 = 0; + static mut Y: bool = 0; + + // настоящая точка входа в программу + unsafe fn main() -> ! { + interrupt::disable(); + + // .. + + // вызов пользовательского кода; передача ссылок на статические переменные + init(init::Context { + resources: init::Resources { + X: &mut X, + }, + // .. + }); + + // .. + + interrupt::enable(); + + // .. + } + + // обработчик прерывания,с которым связан `foo` + #[no_mangle] + unsafe fn UART0() { + // вызов пользовательского кода; передача ссылок на статические переменные + foo(foo::Context { + resources: foo::Resources { + X: &mut X, + }, + // .. + }); + } + + // обработчик прерывания,с которым связан `bar` + #[no_mangle] + unsafe fn UART1() { + // вызов пользовательского кода; передача ссылок на статические переменные + bar(bar::Context { + resources: bar::Resources { + X: &mut X, + Y: &mut Y, + }, + // .. + }); + } +} +``` |
