sys_task_info()

实现一个 sys_task_info 的系统调用,它的主要功能是:

  • 任务控制块相关信息(任务状态)
  • 任务使用的系统调用次数
  • 系统调用时刻距离任务第一次被调度时刻的时长
    即struct TaskInfo中给我们写好的status、syscall_times和time
    框架已经给好了
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ///os/src/syscall/process.rs

    /// Task information
    #[allow(dead_code)]
    pub struct TaskInfo {
    /// Task status in it's life cycle
    status: TaskStatus,
    /// The numbers of syscall called by task
    syscall_times: [u32; MAX_SYSCALL_NUM],
    /// Total running time of task
    time: usize,
    }

    /// YOUR JOB: Finish sys_task_info to pass testcases
    pub fn sys_task_info(_ti: *mut TaskInfo) -> isize {
    trace!("kernel: sys_task_info");
    0
    }
    这里 _ti 是指向TaskInfo结构体内存位置的一个裸指针,在 unsafe 块中,通过解引用 _ti 指针,并使用 *_ti 访问其指向的内存位置。这样可以直接修改 _ti 指向的内存中的数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    trace!("kernel: sys_task_info");
    unsafe {
    *_ti = TaskInfo {
    status: TaskStatus::Running,
    syscall_times: _get_syscall_times(),
    time: get_time_ms(),
    }
    }
    0
    接下来完成各个模块的定义

status

因为是查询当前任务,任务状态即是Running

syscall_times

这里syscall_times采用桶计数的方法,定义一个[u32; MAX_SYSCALL_NUM]的数组,以SYSCALL_ID 为索引去记录每个syscall的调用次数。首先在 os/src/task/task.rspub struct TaskControlBlock 中定义 pub sys_call_times: [u32; MAX_SYSCALL_NUM]

1
2
3
4
5
6
7
8
9
10
/// The task control block (TCB) of a task.
#[derive(Copy, Clone)]
pub struct TaskControlBlock {
/// The task status in it's lifecycle
pub task_status: TaskStatus,
/// The task context
pub task_cx: TaskContext,
/// syscall time count
pub sys_call_times: [u32; MAX_SYSCALL_NUM],// add
}

再在 os/src/task/mod.rsTaskManager 中定义函数 set_syscall_records() ,在外部对其进行封装 _set_syscall_records()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// os/src/task/mod.rs
impl TaskManager {
/// Run the first task in task list
...

fn set_syscall_record(&self, syscall_id: usize) {
let mut inner = self.inner.exclusive_access();
let current = inner.current_task;
inner.tasks[current].sys_call_times[syscall_id] += 1;
drop(inner);
}
}

/// Set the syscall record of current task
pub fn _set_syscall_record(syscall_id: usize) {
TASK_MANAGER.set_syscall_record(syscall_id);
}

最后在 os/src/syscall/mod.rssyscall 函数中调用 _set_syscall_records() ,到达记录每次系统调用的作用
部分涉及到的模块代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/// os/src/task/mod.rs
pub struct TaskManager {
/// total number of tasks
num_app: usize,
/// use inner value to get mutable access
inner: UPSafeCell<TaskManagerInner>,
}

/// Inner of Task Manager
pub struct TaskManagerInner {
/// task list
tasks: [TaskControlBlock; MAX_APP_NUM],
/// id of current `Running` task
current_task: usize,
}

/// 全局变量TASK_MANAGER,任务管理器
lazy_static! {
/// Global variable: TASK_MANAGER
pub static ref TASK_MANAGER: TaskManager = {
let num_app = get_num_app();
let mut tasks = [TaskControlBlock {
task_cx: TaskContext::zero_init(),
task_status: TaskStatus::UnInit,
sys_call_times: [0; MAX_SYSCALL_NUM],
}; MAX_APP_NUM];
for (i, task) in tasks.iter_mut().enumerate() {
task.task_cx = TaskContext::goto_restore(init_app_cx(i));
task.task_status = TaskStatus::Ready;
}
TaskManager {
num_app,
inner: unsafe {
UPSafeCell::new(TaskManagerInner {
tasks,
current_task: 0,
})
},
}
};
}

/// os/src/task/task.rs
/// The task control block (TCB) of a task.
#[derive(Copy, Clone)]
pub struct TaskControlBlock {
/// The task status in it's lifecycle
pub task_status: TaskStatus,
/// The task context
pub task_cx: TaskContext,
/// syscall time count
pub sys_call_times: [u32; MAX_SYSCALL_NUM],
}

/// The status of a task
#[derive(Copy, Clone, PartialEq)]
pub enum TaskStatus {
/// uninitialized
UnInit,
/// ready to run
Ready,
/// running
Running,
/// exited
Exited,
}

time

使用 os/src/timer.rs 中给好的 get_time_ms() 即可

1
2
3
4
5
6
/// get current time in milliseconds
#[allow(dead_code)]
pub fn get_time_ms() -> usize {
time::read() * MSEC_PER_SEC / CLOCK_FREQ
}