aboutsummaryrefslogtreecommitdiff
path: root/book/ru/src/internals/access.md
diff options
context:
space:
mode:
Diffstat (limited to 'book/ru/src/internals/access.md')
-rw-r--r--book/ru/src/internals/access.md158
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,
+ },
+ // ..
+ });
+ }
+}
+```