2024-06-07
最后编辑于:2024-09-15
main.rs
中使用程序名称调用InitTask::from_elf
加载程序,得到任务的基本构造信息InitTask
pub async fn from_elf(
parent: Weak<Task>,
file: Phys,
virt: Pin<Arsc<Virt>>,
lib_path: Vec<&Path>,
args: Vec<String>,
) -> Result<Self, Error>;
pub struct InitTask {
main: Weak<Task>,
parent: Weak<Task>,
virt: Pin<Arsc<Virt>>,
tf: TrapFrame,
files: Files,
}
InitTask
的spawn
方法,分配task id,根据信息创建Task
和TaskState
然后放入任务队列ksync::critical(|| TASKS.lock().insert(tid, task.clone()));
let fut = TaskFut::new(ts.virt.clone(), user_loop(ts, self.tf));
executor().spawn(fut).detach();
创建任务的TaskFut
后,使用async_task::Task::detach分离此Future。意思是这个Future会放在后台执行,当前的async块无需等待此Future的完成
这里的spawn
是对async_task::spawn的一个包装,其内部会由async_task::spawn
返回一个Runnable
和async_task::Task
(Runnable
用于poll
Future, async_task::Task
用于等待返回),并会调用Runnable
的schedule
方法将这个任务放入async_task
的调度队列。最后只返回async_task::Task
。
Runnable
还提供了run()
来立即进行一次poll
,在任务被调度实际执行时会使用。
Method
run()
polls the task’s future once. Then, theRunnable
vanishes and only reappears when itsWaker
wakes the task, thus scheduling it to be run again.
注意这里的async_task::Task
和Task
并不一致,每次使用spawn
得到的async_task::Task
都会立即调用async_task::Task::detach
消耗掉。也就是说我们不会等待async_task::Task
,只使用了async_task的调度功能。