Add support for '/proc/[pid]/stat'
Many field values are displayed as 0
This commit is contained in:
parent
28c0d55c88
commit
865e38258b
@ -8,6 +8,7 @@ use self::cwd::ProcCwdSymINode;
|
|||||||
use self::exe::ProcExeSymINode;
|
use self::exe::ProcExeSymINode;
|
||||||
use self::fd::LockedProcFdDirINode;
|
use self::fd::LockedProcFdDirINode;
|
||||||
use self::root::ProcRootSymINode;
|
use self::root::ProcRootSymINode;
|
||||||
|
use self::stat::ProcStatINode;
|
||||||
|
|
||||||
mod cmdline;
|
mod cmdline;
|
||||||
mod comm;
|
mod comm;
|
||||||
@ -15,6 +16,7 @@ mod cwd;
|
|||||||
mod exe;
|
mod exe;
|
||||||
mod fd;
|
mod fd;
|
||||||
mod root;
|
mod root;
|
||||||
|
mod stat;
|
||||||
|
|
||||||
pub struct LockedPidDirINode(RwLock<PidDirINode>);
|
pub struct LockedPidDirINode(RwLock<PidDirINode>);
|
||||||
|
|
||||||
@ -58,6 +60,9 @@ impl LockedPidDirINode {
|
|||||||
// comm
|
// comm
|
||||||
let comm_inode = ProcCommINode::new(&file.process_ref);
|
let comm_inode = ProcCommINode::new(&file.process_ref);
|
||||||
file.entries.insert(String::from("comm"), comm_inode);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
185
src/libos/src/fs/procfs/pid/stat.rs
Normal file
185
src/libos/src/fs/procfs/pid/stat.rs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct ProcStatINode(ProcessRef);
|
||||||
|
|
||||||
|
impl ProcStatINode {
|
||||||
|
pub fn new(process_ref: &ProcessRef) -> Arc<dyn INode> {
|
||||||
|
Arc::new(File::new(Self(Arc::clone(process_ref))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcINode for ProcStatINode {
|
||||||
|
fn generate_data_in_bytes(&self) -> vfs::Result<Vec<u8>> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,25 @@ static int test_readlink_from_procfs(const char *proc_inode, char *buf, int buf_
|
|||||||
return 0;
|
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
|
// Test cases for procfs
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -136,41 +155,45 @@ static int test_read_from_proc_self_comm() {
|
|||||||
return 0;
|
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() {
|
static int test_read_from_proc_meminfo() {
|
||||||
char meminfo[1024] = { 0 };
|
|
||||||
const char *proc_meminfo = "/proc/meminfo";
|
const char *proc_meminfo = "/proc/meminfo";
|
||||||
|
|
||||||
int fd = open(proc_meminfo, O_RDONLY);
|
if (test_read_from_procfs(proc_meminfo) < 0) {
|
||||||
if (fd < 0) {
|
|
||||||
THROW_ERROR("failed to open file: %s", proc_meminfo);
|
|
||||||
}
|
|
||||||
if (read(fd, meminfo, sizeof(meminfo)) < 0) {
|
|
||||||
THROW_ERROR("failed to read the meminfo");
|
THROW_ERROR("failed to read the meminfo");
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_read_from_proc_cpuinfo() {
|
static int test_read_from_proc_cpuinfo() {
|
||||||
char cpuinfo[1024] = { 0 };
|
|
||||||
const char *proc_cpuinfo = "/proc/cpuinfo";
|
const char *proc_cpuinfo = "/proc/cpuinfo";
|
||||||
int len;
|
|
||||||
|
|
||||||
int fd = open(proc_cpuinfo, O_RDONLY);
|
if (test_read_from_procfs(proc_cpuinfo) < 0) {
|
||||||
if (fd < 0) {
|
THROW_ERROR("failed to read the cpuinfo");
|
||||||
THROW_ERROR("failed to open file: %s", proc_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;
|
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_create_and_unlink_file_from_proc_self_root),
|
||||||
TEST_CASE(test_read_from_proc_self_cmdline),
|
TEST_CASE(test_read_from_proc_self_cmdline),
|
||||||
TEST_CASE(test_read_from_proc_self_comm),
|
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_meminfo),
|
||||||
TEST_CASE(test_read_from_proc_cpuinfo),
|
TEST_CASE(test_read_from_proc_cpuinfo),
|
||||||
TEST_CASE(test_statfs),
|
TEST_CASE(test_statfs),
|
||||||
|
Loading…
Reference in New Issue
Block a user