Skip to content
11 changes: 6 additions & 5 deletions kernel/src/filesystem/procfs/cmdline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
filesystem::{
procfs::{
template::{Builder, FileOps, ProcFileBuilder},
utils::proc_read,
utils::proc_read_snapshot,
},
vfs::{FilePrivateData, IndexNode, InodeMode},
},
Expand Down Expand Up @@ -53,10 +53,11 @@ impl FileOps for CmdlineFileOps {
offset: usize,
len: usize,
buf: &mut [u8],
_data: MutexGuard<FilePrivateData>,
mut data: MutexGuard<FilePrivateData>,
) -> Result<usize, SystemError> {
let content = Self::generate_cmdline_content();

proc_read(offset, len, buf, &content)
// `single_open()`: one fd sees one kernel command line record.
proc_read_snapshot(offset, len, buf, &mut data, || {
Ok(Self::generate_cmdline_content())
})
}
}
34 changes: 19 additions & 15 deletions kernel/src/filesystem/procfs/cpuinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
filesystem::{
procfs::{
template::{Builder, FileOps, ProcFileBuilder},
utils::proc_read,
utils::proc_read_snapshot,
},
vfs::{IndexNode, InodeMode},
},
Expand Down Expand Up @@ -34,22 +34,26 @@ impl FileOps for CpuInfoFileOps {
offset: usize,
len: usize,
buf: &mut [u8],
_: crate::libs::mutex::MutexGuard<crate::filesystem::vfs::FilePrivateData>,
mut data: crate::libs::mutex::MutexGuard<crate::filesystem::vfs::FilePrivateData>,
) -> Result<usize, SystemError> {
let mut data: Vec<u8> = vec![];
let cpu_manager = smp_cpu_manager();

// 遍历所有present的CPU
for cpu_id in cpu_manager.present_cpus().iter_cpu() {
// 生成每个 CPU 的信息
let cpu_info = generate_cpu_info(cpu_id);
data.extend_from_slice(cpu_info.as_bytes());

// 在每个CPU信息之间添加空行分隔
data.push(b'\n');
}
// `seq_file` (Linux `seq_open(&cpuinfo_op)`, `fs/proc/cpuinfo.c`): one
// fd sees one rendered record.
proc_read_snapshot(offset, len, buf, &mut data, || {
let mut content: Vec<u8> = vec![];
let cpu_manager = smp_cpu_manager();

// Walk every present CPU.
for cpu_id in cpu_manager.present_cpus().iter_cpu() {
// Render this CPU's record.
let cpu_info = generate_cpu_info(cpu_id);
content.extend_from_slice(cpu_info.as_bytes());

// Blank line between CPU records, as Linux does.
content.push(b'\n');
}

proc_read(offset, len, buf, &data)
Ok(content)
})
}
}

Expand Down
10 changes: 6 additions & 4 deletions kernel/src/filesystem/procfs/loadavg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
filesystem::{
procfs::{
template::{Builder, FileOps, ProcFileBuilder},
utils::{proc_read, trim_string},
utils::{proc_read_snapshot, trim_string},
},
vfs::{FilePrivateData, IndexNode, InodeMode},
},
Expand Down Expand Up @@ -71,9 +71,11 @@ impl FileOps for LoadavgFileOps {
offset: usize,
len: usize,
buf: &mut [u8],
_data: MutexGuard<FilePrivateData>,
mut data: MutexGuard<FilePrivateData>,
) -> Result<usize, SystemError> {
let content = Self::generate_loadavg_content();
proc_read(offset, len, buf, &content)
// `single_open()`: one fd sees one load-average record.
proc_read_snapshot(offset, len, buf, &mut data, || {
Ok(Self::generate_loadavg_content())
})
}
}
10 changes: 6 additions & 4 deletions kernel/src/filesystem/procfs/meminfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
filesystem::{
procfs::{
template::{Builder, FileOps, ProcFileBuilder},
utils::{proc_read, trim_string},
utils::{proc_read_snapshot, trim_string},
},
vfs::{FilePrivateData, IndexNode, InodeMode},
},
Expand Down Expand Up @@ -107,9 +107,11 @@ impl FileOps for MeminfoFileOps {
offset: usize,
len: usize,
buf: &mut [u8],
_data: MutexGuard<FilePrivateData>,
mut data: MutexGuard<FilePrivateData>,
) -> Result<usize, SystemError> {
let content = Self::generate_meminfo_content();
proc_read(offset, len, buf, &content)
// `single_open()`: one fd sees one meminfo record.
proc_read_snapshot(offset, len, buf, &mut data, || {
Ok(Self::generate_meminfo_content())
})
}
}
35 changes: 30 additions & 5 deletions kernel/src/filesystem/procfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
//! 实现 Linux 兼容的 /proc 文件系统

use crate::mm::ucontext::AddressSpace;
use alloc::{sync::Arc, vec::Vec};
use alloc::sync::Arc;
use system_error::SystemError;

use crate::{
libs::once::Once,
process::{cred::Cred, namespace::pid_namespace::INIT_PID_NAMESPACE, ProcessManager},
process::{
cred::Cred, namespace::net_namespace::NetNamespace,
namespace::pid_namespace::INIT_PID_NAMESPACE, ProcessManager,
},
};

use super::vfs::mount::MountFlags;
use super::vfs::InodeMode;
use mount::MountView;

mod cmdline;
mod cpuinfo;
Expand Down Expand Up @@ -50,17 +54,38 @@ pub(super) use template::Builder;
/// procfs 文件私有数据
#[derive(Debug, Clone)]
pub struct ProcfsFilePrivateData {
pub data: Vec<u8>,
pub open_cred: Arc<Cred>,
pub pinned_vm: Option<Arc<AddressSpace>>,
/// Address space this fd was opened on, taken by `open()` of the files that
/// address one (`/proc/[pid]/mem`, `/proc/[pid]/maps`).
///
/// The descriptor, deliberately not the memory: Linux `proc_mem_open()`
/// grabs the `mm_struct` and then drops the user reference again
/// ("but do not pin its memory"), so an `execve()` or an exit in the target
/// still tears the mappings down while this fd stays open. Each read
/// re-checks the user count (`mmget_not_zero()`), which is how both files
/// learn that there is nothing left to serve.
pub(crate) pinned_vm: Option<Arc<AddressSpace>>,
/// Streaming state of a seq-style record (Linux `struct seq_file`). Only
/// `utils::proc_read_seq()` and `utils::proc_read_snapshot()` touch it.
pub(crate) seq: utils::ProcfsSeq,
/// Mount namespace and root directory pinned by `open()` for
/// `/proc/[pid]/{mounts,mountinfo,mountstats}`, as `mounts_open_common()`
/// does; `None` for every other procfs file.
pub(crate) mount_view: Option<MountView>,
/// Network namespace pinned by `open()` for the files under `/proc/net`,
/// as `seq_open_net()` stores it in `seq_net_private`; `None` for every
/// other procfs file.
pub(crate) net_ns: Option<Arc<NetNamespace>>,
}

impl ProcfsFilePrivateData {
pub fn new() -> Self {
ProcfsFilePrivateData {
data: Vec::new(),
open_cred: ProcessManager::current_pcb().cred(),
pinned_vm: None,
seq: utils::ProcfsSeq::default(),
mount_view: None,
net_ns: None,
}
}
}
Expand Down
Loading
Loading