进程创建

2024-06-07

最后编辑于:2024-09-15

    #umi
    #进程
    #OS
    #Rust

创建流程

  1. 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,
}
  1. 调用InitTaskspawn方法,分配task id,根据信息创建TaskTaskState 然后放入任务队列
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返回一个Runnableasync_task::Task(Runnable用于pollFuture, async_task::Task用于等待返回),并会调用Runnableschedule方法将这个任务放入async_task的调度队列。最后只返回async_task::Task

Runnable还提供了run()来立即进行一次poll,在任务被调度实际执行时会使用。

Method run() polls the task’s future once. Then, the Runnablevanishes and only reappears when its Waker wakes the task, thus scheduling it to be run again.

注意这里的async_task::TaskTask并不一致,每次使用spawn得到的async_task::Task都会立即调用async_task::Task::detach消耗掉。也就是说我们不会等待async_task::Task,只使用了async_task的调度功能。