Add partial support for '/proc/stat' and '/proc/[pid]/stat'
This commit is contained in:
parent
178bd023e3
commit
64c75e6d40
@ -336,7 +336,7 @@ impl HNode {
|
||||
}
|
||||
}
|
||||
|
||||
trait IntoFsError {
|
||||
pub trait IntoFsError {
|
||||
fn into_fs_error(self) -> FsError;
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,14 @@ use self::meminfo::MemInfoINode;
|
||||
use self::pid::LockedPidDirINode;
|
||||
use self::proc_inode::{Dir, DirProcINode, File, ProcINode, SymLink};
|
||||
use self::self_::SelfSymINode;
|
||||
use self::stat::StatINode;
|
||||
|
||||
mod cpuinfo;
|
||||
mod meminfo;
|
||||
mod pid;
|
||||
mod proc_inode;
|
||||
mod self_;
|
||||
mod stat;
|
||||
|
||||
// Same with the procfs on Linux
|
||||
const PROC_SUPER_MAGIC: usize = 0x9fa0;
|
||||
@ -97,7 +99,6 @@ impl LockedProcRootINode {
|
||||
fn init(&self, fs: &Arc<ProcFS>) {
|
||||
let mut file = self.0.write().unwrap();
|
||||
file.this = Arc::downgrade(&fs.root);
|
||||
// Currently, we only init the 'cpuinfo', 'meminfo' and 'self' entry.
|
||||
// TODO: Add more entries for root.
|
||||
// All [pid] entries are lazy-initialized at the find() step.
|
||||
let cpuinfo_inode = CpuInfoINode::new();
|
||||
@ -109,6 +110,9 @@ impl LockedProcRootINode {
|
||||
let self_inode = SelfSymINode::new();
|
||||
file.non_volatile_entries
|
||||
.insert(String::from("self"), self_inode);
|
||||
let stat_inode = StatINode::new();
|
||||
file.non_volatile_entries
|
||||
.insert(String::from("stat"), stat_inode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,11 @@ impl ProcINode for ProcStatINode {
|
||||
let stime = 0;
|
||||
let cutime = 0;
|
||||
let cstime = 0;
|
||||
let priority = 0;
|
||||
let nice = 0;
|
||||
let priority = main_thread.nice().read().unwrap().to_priority_val();
|
||||
let nice = main_thread.nice().read().unwrap().raw_val();
|
||||
let num_threads = self.0.threads().len();
|
||||
let itrealvalue = 0;
|
||||
let starttime = 0;
|
||||
let starttime = self.0.start_time();
|
||||
let vsize = main_thread.vm().get_process_range().size();
|
||||
let rss = 0;
|
||||
let rsslim = 0;
|
||||
|
48
src/libos/src/fs/procfs/stat.rs
Normal file
48
src/libos/src/fs/procfs/stat.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use super::*;
|
||||
use crate::fs::hostfs::IntoFsError;
|
||||
use std::untrusted::fs;
|
||||
|
||||
/// It returns most of the information from host OS's "/proc/stat",
|
||||
/// and some fields will be filled in with LibOS's information.
|
||||
pub struct StatINode;
|
||||
|
||||
impl StatINode {
|
||||
pub fn new() -> Arc<dyn INode> {
|
||||
Arc::new(File::new(Self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcINode for StatINode {
|
||||
fn generate_data_in_bytes(&self) -> vfs::Result<Vec<u8>> {
|
||||
let mut host_stat = fs::read_to_string("/proc/stat").map_err(|e| e.into_fs_error())?;
|
||||
let boot_time = crate::time::up_time::boot_time_since_epoch()
|
||||
.as_secs()
|
||||
.to_string();
|
||||
fill_in_stat(&mut host_stat, "btime", &boot_time);
|
||||
let procs_running = {
|
||||
let mut processes = crate::process::table::get_all_processes();
|
||||
processes.retain(|p| p.status() == crate::process::ProcessStatus::Running);
|
||||
processes.len().to_string()
|
||||
};
|
||||
fill_in_stat(&mut host_stat, "procs_running", &procs_running);
|
||||
Ok(host_stat.into_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_in_stat(stat: &mut String, pat: &str, val: &str) {
|
||||
let start_idx = stat.find(pat).unwrap_or_else(|| {
|
||||
error!("failed to find {} in host's /proc/stat", pat);
|
||||
panic!()
|
||||
}) + pat.len()
|
||||
+ 1;
|
||||
let end_idx = stat
|
||||
.chars()
|
||||
.skip(start_idx)
|
||||
.position(|c| c == '\n')
|
||||
.unwrap_or_else(|| {
|
||||
error!("invalid format of host's /proc/stat");
|
||||
panic!()
|
||||
})
|
||||
+ start_idx;
|
||||
stat.replace_range(start_idx..end_idx, val);
|
||||
}
|
@ -135,9 +135,11 @@ impl ProcessBuilder {
|
||||
let sig_dispositions = RwLock::new(self.sig_dispositions.unwrap_or_default());
|
||||
let sig_queues = RwLock::new(SigQueues::new());
|
||||
let forced_exit_status = ForcedExitStatus::new();
|
||||
let start_time = crate::time::up_time::get().unwrap();
|
||||
Arc::new(Process {
|
||||
pid,
|
||||
exec_path,
|
||||
start_time,
|
||||
umask,
|
||||
parent,
|
||||
pgrp,
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::wait::WaitQueue;
|
||||
use super::{ForcedExitStatus, ProcessGrpRef, ProcessRef, TermStatus, ThreadRef};
|
||||
@ -16,6 +17,7 @@ pub struct Process {
|
||||
// Immutable info
|
||||
pid: pid_t,
|
||||
exec_path: String,
|
||||
start_time: Duration,
|
||||
// Mutable info
|
||||
parent: Option<RwLock<ProcessRef>>,
|
||||
pgrp: RwLock<Option<ProcessGrpRef>>,
|
||||
@ -124,6 +126,13 @@ impl Process {
|
||||
&self.exec_path
|
||||
}
|
||||
|
||||
/// Get the time the process started after system boot
|
||||
///
|
||||
/// The value is expressed in clock ticks
|
||||
pub fn start_time(&self) -> u64 {
|
||||
self.start_time.as_millis() as u64 * crate::time::SC_CLK_TCK / 1000
|
||||
}
|
||||
|
||||
/// Get the file mode creation mask
|
||||
pub fn umask(&self) -> FileMode {
|
||||
self.umask.read().unwrap().clone()
|
||||
|
@ -46,6 +46,15 @@ impl NiceValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_val(&self) -> i32 {
|
||||
self.value
|
||||
}
|
||||
|
||||
/// Convert [19,-20] to priority value [39,0].
|
||||
pub fn to_priority_val(&self) -> i32 {
|
||||
self.value - Self::MIN_PRIO
|
||||
}
|
||||
|
||||
/// Convert [19,-20] to rlimit style value [1,40].
|
||||
pub fn to_rlimit_val(&self) -> i32 {
|
||||
Self::MAX_PRIO - self.value + 1
|
||||
|
@ -24,6 +24,9 @@ pub type suseconds_t = i64;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type clock_t = i64;
|
||||
|
||||
/// Clock ticks per second
|
||||
pub const SC_CLK_TCK: u64 = 100;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
|
@ -5,10 +5,18 @@ lazy_static! {
|
||||
static ref BOOT_TIME_STAMP: Duration = do_clock_gettime(ClockID::CLOCK_MONOTONIC_RAW)
|
||||
.unwrap()
|
||||
.as_duration();
|
||||
static ref BOOT_TIME_STAMP_SINCE_EPOCH: Duration = do_clock_gettime(ClockID::CLOCK_REALTIME)
|
||||
.unwrap()
|
||||
.as_duration();
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
*BOOT_TIME_STAMP;
|
||||
*BOOT_TIME_STAMP_SINCE_EPOCH;
|
||||
}
|
||||
|
||||
pub fn boot_time_since_epoch() -> Duration {
|
||||
*BOOT_TIME_STAMP_SINCE_EPOCH
|
||||
}
|
||||
|
||||
pub fn get() -> Option<Duration> {
|
||||
|
@ -48,7 +48,6 @@ static int test_read_from_procfs(const char *proc_inode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Test cases for procfs
|
||||
// ============================================================================
|
||||
@ -207,6 +206,15 @@ static int test_read_from_proc_cpuinfo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_read_from_proc_stat() {
|
||||
const char *proc_stat = "/proc/stat";
|
||||
|
||||
if (test_read_from_procfs(proc_stat) < 0) {
|
||||
THROW_ERROR("failed to read the stat");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PROC_SUPER_MAGIC 0x9fa0
|
||||
static int test_statfs() {
|
||||
const char *file_path = "/proc/cpuinfo";
|
||||
@ -288,6 +296,7 @@ static test_case_t test_cases[] = {
|
||||
TEST_CASE(test_read_from_proc_self_stat),
|
||||
TEST_CASE(test_read_from_proc_meminfo),
|
||||
TEST_CASE(test_read_from_proc_cpuinfo),
|
||||
TEST_CASE(test_read_from_proc_stat),
|
||||
TEST_CASE(test_statfs),
|
||||
TEST_CASE(test_readdir_root),
|
||||
TEST_CASE(test_readdir_self),
|
||||
|
Loading…
Reference in New Issue
Block a user