mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 16:33:24 +00:00
Add /proc/[pid]/stat and /proc/[pid]/status
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
da5e7a21cb
commit
9f188837ae
@ -13,6 +13,7 @@ TME = "TME"
|
||||
BA = "BA"
|
||||
ND = "ND"
|
||||
Fo = "Fo"
|
||||
Inh = "Inh"
|
||||
|
||||
# Files with svg suffix are ignored to check.
|
||||
[type.svg]
|
||||
|
@ -66,6 +66,14 @@ impl FileTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.table.slots_len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.table.is_empty()
|
||||
}
|
||||
|
||||
pub fn dup(&mut self, fd: FileDesc, new_fd: FileDesc, flags: FdFlags) -> Result<FileDesc> {
|
||||
let file = self
|
||||
.table
|
||||
@ -80,12 +88,12 @@ impl FileTable {
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
for idx in new_fd + 1..self.table.slots_len() {
|
||||
for idx in new_fd + 1..self.len() {
|
||||
if self.table.get(idx).is_none() {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
self.table.slots_len()
|
||||
self.len()
|
||||
};
|
||||
|
||||
let min_free_fd = get_min_free_fd();
|
||||
|
@ -16,6 +16,8 @@ mod cmdline;
|
||||
mod comm;
|
||||
mod exe;
|
||||
mod fd;
|
||||
mod stat;
|
||||
mod status;
|
||||
|
||||
/// Represents the inode at `/proc/[pid]`.
|
||||
pub struct PidDirOps(Arc<Process>);
|
||||
@ -51,6 +53,8 @@ impl DirOps for PidDirOps {
|
||||
"comm" => CommFileOps::new_inode(self.0.clone(), this_ptr.clone()),
|
||||
"fd" => FdDirOps::new_inode(self.0.clone(), this_ptr.clone()),
|
||||
"cmdline" => CmdlineFileOps::new_inode(self.0.clone(), this_ptr.clone()),
|
||||
"status" => status::StatusFileOps::new_inode(self.0.clone(), this_ptr.clone()),
|
||||
"stat" => stat::StatFileOps::new_inode(self.0.clone(), this_ptr.clone()),
|
||||
_ => return_errno!(Errno::ENOENT),
|
||||
};
|
||||
Ok(inode)
|
||||
@ -74,5 +78,11 @@ impl DirOps for PidDirOps {
|
||||
cached_children.put_entry_if_not_found("cmdline", || {
|
||||
CmdlineFileOps::new_inode(self.0.clone(), this_ptr.clone())
|
||||
});
|
||||
cached_children.put_entry_if_not_found("status", || {
|
||||
status::StatusFileOps::new_inode(self.0.clone(), this_ptr.clone())
|
||||
});
|
||||
cached_children.put_entry_if_not_found("stat", || {
|
||||
stat::StatFileOps::new_inode(self.0.clone(), this_ptr.clone())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
47
kernel/src/fs/procfs/pid/stat.rs
Normal file
47
kernel/src/fs/procfs/pid/stat.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
procfs::template::{FileOps, ProcFileBuilder},
|
||||
utils::Inode,
|
||||
},
|
||||
prelude::*,
|
||||
Process,
|
||||
};
|
||||
|
||||
/// Represents the inode at `/proc/[pid]/stat`.
|
||||
/// The fields are the same as the ones in `/proc/[pid]/status`. But the format is different.
|
||||
/// See https://github.com/torvalds/linux/blob/ce1c54fdff7c4556b08f5b875a331d8952e8b6b7/fs/proc/array.c#L467
|
||||
/// FIXME: Some fields are not implemented yet.
|
||||
pub struct StatFileOps(Arc<Process>);
|
||||
|
||||
impl StatFileOps {
|
||||
pub fn new_inode(process_ref: Arc<Process>, parent: Weak<dyn Inode>) -> Arc<dyn Inode> {
|
||||
ProcFileBuilder::new(Self(process_ref))
|
||||
.parent(parent)
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl FileOps for StatFileOps {
|
||||
fn data(&self) -> Result<Vec<u8>> {
|
||||
let process = &self.0;
|
||||
let mut stat_output = String::new();
|
||||
writeln!(
|
||||
stat_output,
|
||||
"{} {} {} {} {} {} {}",
|
||||
process.executable_path(),
|
||||
process.pid(),
|
||||
process.pid(),
|
||||
process.parent().pid(),
|
||||
process.parent().pid(),
|
||||
process.file_table().lock().len(),
|
||||
process.tasks().lock().len()
|
||||
)
|
||||
.unwrap();
|
||||
Ok(stat_output.into_bytes())
|
||||
}
|
||||
}
|
89
kernel/src/fs/procfs/pid/status.rs
Normal file
89
kernel/src/fs/procfs/pid/status.rs
Normal file
@ -0,0 +1,89 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
procfs::template::{FileOps, ProcFileBuilder},
|
||||
utils::Inode,
|
||||
},
|
||||
prelude::*,
|
||||
Process,
|
||||
};
|
||||
|
||||
/// Represents the inode at `/proc/[pid]/status`.
|
||||
/// See https://github.com/torvalds/linux/blob/ce1c54fdff7c4556b08f5b875a331d8952e8b6b7/fs/proc/array.c#L148
|
||||
/// FIXME: Some fields are not implemented yet.
|
||||
///
|
||||
/// Fields:
|
||||
/// - Name: The name of the process.
|
||||
/// - State: The current state of the process (e.g., R for running, S for sleeping).
|
||||
/// - Tgid: The Thread Group ID, which is the same as the process ID for the main thread.
|
||||
/// - Pid: The process ID.
|
||||
/// - PPid: The parent process ID.
|
||||
/// - TracerPid: The PID of the process tracing this process, or 0 if not being traced.
|
||||
/// - Uid: Real, effective, saved set, and filesystem UIDs.
|
||||
/// - Gid: Real, effective, saved set, and filesystem GIDs.
|
||||
/// - FDSize: The number of file descriptor slots currently allocated.
|
||||
/// - Groups: Supplementary group IDs.
|
||||
/// - VmPeak: Peak virtual memory size.
|
||||
/// - VmSize: Current virtual memory size.
|
||||
/// - VmLck: Locked memory size.
|
||||
/// - VmPin: Pinned memory size.
|
||||
/// - VmHWM: Peak resident set size ("high water mark").
|
||||
/// - VmRSS: Resident set size.
|
||||
/// - VmData: Size of data segment.
|
||||
/// - VmStk: Size of stack segment.
|
||||
/// - VmExe: Size of text segment.
|
||||
/// - VmLib: Shared library code size.
|
||||
/// - VmPTE: Page table entries size.
|
||||
/// - VmSwap: Swapped-out virtual memory size by anonymous private pages.
|
||||
/// - Threads: Number of threads in this process.
|
||||
/// - SigQ: Current signal queue size and limit.
|
||||
/// - SigPnd: Threads pending signals.
|
||||
/// - ShdPnd: Shared pending signals.
|
||||
/// - SigBlk: Blocked signals.
|
||||
/// - SigIgn: Ignored signals.
|
||||
/// - SigCgt: Caught signals.
|
||||
/// - CapInh: Inheritable capabilities.
|
||||
/// - CapPrm: Permitted capabilities.
|
||||
/// - CapEff: Effective capabilities.
|
||||
/// - CapBnd: Bounding set.
|
||||
/// - CapAmb: Ambient capabilities.
|
||||
/// - Seccomp: Seccomp mode.
|
||||
/// - Cpus_allowed: CPUs allowed for this process.
|
||||
/// - Cpus_allowed_list: List of CPUs allowed for this process.
|
||||
/// - Mems_allowed: Memory nodes allowed for this process.
|
||||
/// - Mems_allowed_list: List of memory nodes allowed for this process.
|
||||
/// - voluntary_ctxt_switches: Number of voluntary context switches.
|
||||
/// - nonvoluntary_ctxt_switches: Number of nonvoluntary context switches.
|
||||
pub struct StatusFileOps(Arc<Process>);
|
||||
|
||||
impl StatusFileOps {
|
||||
pub fn new_inode(process_ref: Arc<Process>, parent: Weak<dyn Inode>) -> Arc<dyn Inode> {
|
||||
ProcFileBuilder::new(Self(process_ref))
|
||||
.parent(parent)
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl FileOps for StatusFileOps {
|
||||
fn data(&self) -> Result<Vec<u8>> {
|
||||
let process = &self.0;
|
||||
let mut status_output = String::new();
|
||||
writeln!(status_output, "Name:\t{}", process.executable_path()).unwrap();
|
||||
writeln!(status_output, "Tgid:\t{}", process.pid()).unwrap();
|
||||
writeln!(status_output, "Pid:\t{}", process.pid()).unwrap();
|
||||
writeln!(status_output, "PPid:\t{}", process.parent().pid()).unwrap();
|
||||
writeln!(status_output, "TracerPid:\t{}", process.parent().pid()).unwrap(); // Assuming TracerPid is the same as PPid
|
||||
writeln!(
|
||||
status_output,
|
||||
"FDSize:\t{}",
|
||||
process.file_table().lock().len()
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(status_output, "Threads:\t{}", process.tasks().lock().len()).unwrap();
|
||||
Ok(status_output.into_bytes())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user