如何在#[no_std] 环境中使用 Tokio Reactor?
How do I use Tokio Reactor in a #[no_std] environment?
我正在尝试在 Tock OS 嵌入式操作系统上实现期货。我正在尝试在 #[no_std]
环境中使用 Tokio。
我的 Cargo.toml
文件如下所示:
[package]
name = "nrf52dk"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
[profile.dev]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[dependencies]
cortexm4 = { path = "../../arch/cortex-m4" }
capsules = { path = "../../capsules" }
kernel = { path = "../../kernel" }
nrf52 = { path = "../../chips/nrf52" }
nrf5x = { path = "../../chips/nrf5x" }
futures = {version = "0.2.0", default-features = false }
编译没有错误,但是当我添加 tokio-reactor = "0.1.1"
时,我收到错误:error[E0463]: can't find crate for std
。我明白这是因为 Tokio 从 std 库中导入了一些东西。
是否可以解决这个问题?
据我所知,你不会。 Tokio Reactor 0.1.1 imports many things from the standard library,其中 none 有条件。
大部分导入可能会切换到 libcore
替代方案,但 Arc
需要内存分配,内存位于 alloc
板条箱中。
作为支持 no_std
的板条箱示例,请查看 Futures 0.1.20。这有一个功能标志,可以选择加入需要标准库的功能。
如果您希望这样做,您需要为 Tokio 及其所有依赖项做出大量努力,以添加功能标志以选择加入需要标准库的所有功能。值得向维护者提出一个问题来协调这样的工作。
扩展 Shepmaster 已经说过的话:你不想要 tokio
;它基于 mio
,这不太可能在内核中工作,尤其是在没有堆分配/标准的情况下。
那么如何在这样的环境中驱动任务(生成 Future
s)(这是为 futures
0.1.x 系列编写的):
- 您的 "Executor" ("main loop") 将希望跟踪每个任务的某些状态,例如你是否需要轮询它,也许一些链表来找到那些需要轮询的。
- 你需要那个州的地方;您还需要存储包裹在
Spawn<...>
中的 Future
。应该可以为此使用 "static" 分配的存储空间。
- 你需要实现
UnsafeNotify
(和基本特征Notify
),可能是为了一些原始指针/&'static
对任务(包括状态)的引用; notify
需要能够对任务进行排队,以便以线程安全的方式进行轮询。 {clone,drop}_{raw,id}
函数可以为空,因为无论如何您都将使用静态分配。 notify
如果主循环正在休眠,还需要调度它。队列本身也需要一些全局状态("list head+tail");如果您需要不同的队列,您也可以在 NotifyHandle
中存储对它的引用(例如在 id: usize
参数中)。
- 你甚至可以在同一个 "poll queue" 上尝试 运行 多个循环,祝它线程安全:) future-0.2
ThreadPool
might give some ideas how to do that (or the tokio-threadpool
crate).
- 您可能需要向事件循环添加一些 "timer" 处理;一个定时器应该存储一个
NotifyHandle
到它应该在超时时唤醒的任务,一些状态来跟踪是否超时,并且事件循环需要一个活动(指向)定时器的列表来确定多长时间等待。 (tokio-timer
crate 可能会给你一些关于如何实现它的想法)
- 异步IO的一些类似处理;在用户空间中,您将使用
select
超时(或它的平台特定优化版本),在内核中,您可能必须找到其他方法:)(在 tokio
世界中,这是提供的由 Reactor
,它基于 mio
)
- 完成您想要使用的任务
poll_future_notify
在 futures-0.2 中 NotifyHandle
变成了 Waker
, and UnsafeNotify
became UnsafeWake
; the id: usize
context is gone (just use a struct with all the data you need to implement UnsafeWake
for). Instead of storing Spawn<...>
for a future you need to manually store a LocalMap
for each task, which is then be used to create a Context
with Context::without_spawn
, which is then passed to Future::poll
。
我正在尝试在 Tock OS 嵌入式操作系统上实现期货。我正在尝试在 #[no_std]
环境中使用 Tokio。
我的 Cargo.toml
文件如下所示:
[package]
name = "nrf52dk"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
[profile.dev]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[dependencies]
cortexm4 = { path = "../../arch/cortex-m4" }
capsules = { path = "../../capsules" }
kernel = { path = "../../kernel" }
nrf52 = { path = "../../chips/nrf52" }
nrf5x = { path = "../../chips/nrf5x" }
futures = {version = "0.2.0", default-features = false }
编译没有错误,但是当我添加 tokio-reactor = "0.1.1"
时,我收到错误:error[E0463]: can't find crate for std
。我明白这是因为 Tokio 从 std 库中导入了一些东西。
是否可以解决这个问题?
据我所知,你不会。 Tokio Reactor 0.1.1 imports many things from the standard library,其中 none 有条件。
大部分导入可能会切换到 libcore
替代方案,但 Arc
需要内存分配,内存位于 alloc
板条箱中。
作为支持 no_std
的板条箱示例,请查看 Futures 0.1.20。这有一个功能标志,可以选择加入需要标准库的功能。
如果您希望这样做,您需要为 Tokio 及其所有依赖项做出大量努力,以添加功能标志以选择加入需要标准库的所有功能。值得向维护者提出一个问题来协调这样的工作。
扩展 Shepmaster 已经说过的话:你不想要 tokio
;它基于 mio
,这不太可能在内核中工作,尤其是在没有堆分配/标准的情况下。
那么如何在这样的环境中驱动任务(生成 Future
s)(这是为 futures
0.1.x 系列编写的):
- 您的 "Executor" ("main loop") 将希望跟踪每个任务的某些状态,例如你是否需要轮询它,也许一些链表来找到那些需要轮询的。
- 你需要那个州的地方;您还需要存储包裹在
Spawn<...>
中的Future
。应该可以为此使用 "static" 分配的存储空间。 - 你需要实现
UnsafeNotify
(和基本特征Notify
),可能是为了一些原始指针/&'static
对任务(包括状态)的引用;notify
需要能够对任务进行排队,以便以线程安全的方式进行轮询。{clone,drop}_{raw,id}
函数可以为空,因为无论如何您都将使用静态分配。notify
如果主循环正在休眠,还需要调度它。队列本身也需要一些全局状态("list head+tail");如果您需要不同的队列,您也可以在NotifyHandle
中存储对它的引用(例如在id: usize
参数中)。 - 你甚至可以在同一个 "poll queue" 上尝试 运行 多个循环,祝它线程安全:) future-0.2
ThreadPool
might give some ideas how to do that (or thetokio-threadpool
crate). - 您可能需要向事件循环添加一些 "timer" 处理;一个定时器应该存储一个
NotifyHandle
到它应该在超时时唤醒的任务,一些状态来跟踪是否超时,并且事件循环需要一个活动(指向)定时器的列表来确定多长时间等待。 (tokio-timer
crate 可能会给你一些关于如何实现它的想法) - 异步IO的一些类似处理;在用户空间中,您将使用
select
超时(或它的平台特定优化版本),在内核中,您可能必须找到其他方法:)(在tokio
世界中,这是提供的由Reactor
,它基于mio
) - 完成您想要使用的任务
poll_future_notify
在 futures-0.2 中 NotifyHandle
变成了 Waker
, and UnsafeNotify
became UnsafeWake
; the id: usize
context is gone (just use a struct with all the data you need to implement UnsafeWake
for). Instead of storing Spawn<...>
for a future you need to manually store a LocalMap
for each task, which is then be used to create a Context
with Context::without_spawn
, which is then passed to Future::poll
。