# Контроль доступа Одна из основ 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, }, // .. }); } } ```