diff --git a/src/libos/src/fs/procfs/pid/mod.rs b/src/libos/src/fs/procfs/pid/mod.rs index 9e3705c3..a3297d0b 100644 --- a/src/libos/src/fs/procfs/pid/mod.rs +++ b/src/libos/src/fs/procfs/pid/mod.rs @@ -8,6 +8,7 @@ use self::cwd::ProcCwdSymINode; use self::exe::ProcExeSymINode; use self::fd::LockedProcFdDirINode; use self::root::ProcRootSymINode; +use self::stat::ProcStatINode; mod cmdline; mod comm; @@ -15,6 +16,7 @@ mod cwd; mod exe; mod fd; mod root; +mod stat; pub struct LockedPidDirINode(RwLock); @@ -58,6 +60,9 @@ impl LockedPidDirINode { // comm let comm_inode = ProcCommINode::new(&file.process_ref); file.entries.insert(String::from("comm"), comm_inode); + // stat + let stat_inode = ProcStatINode::new(&file.process_ref); + file.entries.insert(String::from("stat"), stat_inode); Ok(()) } diff --git a/src/libos/src/fs/procfs/pid/stat.rs b/src/libos/src/fs/procfs/pid/stat.rs new file mode 100644 index 00000000..70951d7d --- /dev/null +++ b/src/libos/src/fs/procfs/pid/stat.rs @@ -0,0 +1,185 @@ +use super::*; + +pub struct ProcStatINode(ProcessRef); + +impl ProcStatINode { + pub fn new(process_ref: &ProcessRef) -> Arc { + Arc::new(File::new(Self(Arc::clone(process_ref)))) + } +} + +impl ProcINode for ProcStatINode { + fn generate_data_in_bytes(&self) -> vfs::Result> { + let main_thread = self.0.main_thread().ok_or(FsError::EntryNotFound)?; + + // Get the process status information, some fields are filled with the + // dummy value 0, while some fields are denies to access with value 0. + // TODO: Fill in the dummy fields with meaningful values + let pid = main_thread.tid(); + let comm = String::from_utf8(main_thread.name().as_c_str().to_bytes().to_vec()).unwrap(); + let state = match self.0.status() { + ProcessStatus::Running => "R", + ProcessStatus::Stopped => "T", + ProcessStatus::Zombie => "Z", + }; + let ppid = self.0.parent().pid(); + let pgrp = self.0.pgid(); + let session = pgrp.clone(); + let tty_nr = 0; + let tpgid = pgrp.clone(); + let flags = 0; + let minflt = 0; + let cminflt = 0; + let majflt = 0; + let cmajflt = 0; + let utime = 0; + let stime = 0; + let cutime = 0; + let cstime = 0; + let priority = 0; + let nice = 0; + let num_threads = self.0.threads().len(); + let itrealvalue = 0; + let starttime = 0; + let vsize = main_thread.vm().get_process_range().size(); + let rss = 0; + let rsslim = 0; + let startcode = 0; + let endcode = 0; + let startstack = 0; + let kstkesp = 0; + let kstkeip = 0; + let signal = 0; + let blocked = 0; + let sigignore = 0; + let sigcatch = 0; + let wchan = 0; + let nswap = 0; + let cnswap = 0; + let exit_signal = 0; + let processor = 0; + let rt_priority = 0; + let policy = 0; + let delayacct_blkio_ticks = 0; + let guest_time = 0; + let cguest_time = 0; + let start_data = 0; + let end_data = 0; + let start_brk = 0; + let arg_start = 0; + let arg_end = 0; + let env_start = 0; + let env_end = 0; + let exit_code = 0; + + // Put the information together in the specific format + let result = format!( + "{} \ + ({}) \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {} \ + {}", + pid, + comm, + state, + ppid, + pgrp, + session, + tty_nr, + tpgid, + flags, + minflt, + cminflt, + majflt, + cmajflt, + utime, + stime, + cutime, + cstime, + priority, + nice, + num_threads, + itrealvalue, + starttime, + vsize, + rss, + rsslim, + startcode, + endcode, + startstack, + kstkesp, + kstkeip, + signal, + blocked, + sigignore, + sigcatch, + wchan, + nswap, + cnswap, + exit_signal, + processor, + rt_priority, + policy, + delayacct_blkio_ticks, + guest_time, + cguest_time, + start_data, + end_data, + start_brk, + arg_start, + arg_end, + env_start, + env_end, + exit_code + ) + .into_bytes(); + Ok(result) + } +} diff --git a/test/procfs/main.c b/test/procfs/main.c index 4de32ab8..b5af46ce 100644 --- a/test/procfs/main.c +++ b/test/procfs/main.c @@ -29,6 +29,25 @@ static int test_readlink_from_procfs(const char *proc_inode, char *buf, int buf_ return 0; } +static int test_read_from_procfs(const char *proc_inode) { + char buf[1024] = { 0 }; + int len; + + int fd = open(proc_inode, O_RDONLY); + if (fd < 0) { + THROW_ERROR("failed to open file: %s", proc_inode); + } + do { + len = read(fd, buf, sizeof(buf)); + if (len < 0) { + THROW_ERROR("failed to read: %s", proc_inode); + } + } while (len == sizeof(buf)); + close(fd); + return 0; +} + + // ============================================================================ // Test cases for procfs // ============================================================================ @@ -136,41 +155,45 @@ static int test_read_from_proc_self_comm() { return 0; } +static int test_read_from_proc_self_stat() { + const char *proc_self_stat = "/proc/self/stat"; + FILE *fp = fopen(proc_self_stat, "r"); + if (fp == NULL) { + THROW_ERROR("failed to fopen: %s", proc_self_stat); + } + + int pid, ppid, pgrp; + char comm[32] = { 0 }; + char state[32] = { 0 }; + int ret = fscanf(fp, "%d %s %s %d %d", &pid, comm, state, &ppid, &pgrp); + if (ret != 5) { + THROW_ERROR("failed to parse the first 5 items"); + } + if (pid != getpid()) { + THROW_ERROR("failed to check the result in %s", proc_self_stat); + } + printf("cat %s with the first 5 items:\n%d %s %s %d %d\n", proc_self_stat, pid, comm, + state, ppid, pgrp); + + fclose(fp); + return 0; +} + static int test_read_from_proc_meminfo() { - char meminfo[1024] = { 0 }; const char *proc_meminfo = "/proc/meminfo"; - int fd = open(proc_meminfo, O_RDONLY); - if (fd < 0) { - THROW_ERROR("failed to open file: %s", proc_meminfo); - } - if (read(fd, meminfo, sizeof(meminfo)) < 0) { + if (test_read_from_procfs(proc_meminfo) < 0) { THROW_ERROR("failed to read the meminfo"); } - close(fd); - return 0; } static int test_read_from_proc_cpuinfo() { - char cpuinfo[1024] = { 0 }; const char *proc_cpuinfo = "/proc/cpuinfo"; - int len; - int fd = open(proc_cpuinfo, O_RDONLY); - if (fd < 0) { - THROW_ERROR("failed to open file: %s", proc_cpuinfo); + if (test_read_from_procfs(proc_cpuinfo) < 0) { + THROW_ERROR("failed to read the cpuinfo"); } - do { - len = read(fd, cpuinfo, sizeof(cpuinfo)); - if (len < 0) { - THROW_ERROR("failed to read the cpuinfo"); - } else if (len < sizeof(cpuinfo)) { - break; - } - } while (len == sizeof(cpuinfo)); - close(fd); - return 0; } @@ -252,6 +275,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_create_and_unlink_file_from_proc_self_root), TEST_CASE(test_read_from_proc_self_cmdline), TEST_CASE(test_read_from_proc_self_comm), + 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_statfs),