Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/kernel/ipc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
:maxdepth: 1

signal
ipc_namespace
56 changes: 56 additions & 0 deletions docs/kernel/ipc/ipc_namespace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# IPC Namespace

:::{note}

Author: longjin <longjin@dragonos.org>

:::

本页描述 DragonOS 对 IPC 命名空间(IPC namespace)的当前支持状态与后续计划。目标是对用户暴露与 Linux 一致的语义,并在 DragonOS 现有框架上逐步完善。

## 已支持功能
- IpcNamespace 对象与 NsProxy 集成:
- 新增 `IpcNamespace` 并接入 `NsProxy`,每个任务通过 `nsproxy.ipc_ns` 访问所属 IPC 命名空间。
- 命名空间的创建/继承遵循 `clone/unshare` 语义:
- 未包含 `CLONE_NEWIPC` 时继承父命名空间;
- 包含 `CLONE_NEWIPC` 时创建独立 IPC 命名空间;
- 与 `CLONE_SYSVSEM` 互斥,行为与 Linux 一致。

- SysV SHM(共享内存)按命名空间隔离:
- 将原全局 `SHM_MANAGER` 重构为 per-ns `ShmManager`,所有 `shmget/shmat/shmdt/shmctl` 均在 `current.nsproxy.ipc_ns` 下生效。
- `shmat`/`shmdt`:VMA 记录 `ShmId`,解除映射时精确维护 `map_count`;`IPC_RMID` 后当 `SHM_DEST && map_count==0` 即完成物理回收。
- 基本语义与错误码对齐:`IPC_CREAT|IPC_EXCL`、`ENOENT`、拒绝 `SHM_HUGETLB` 等。

- 基础测试用例:(在 `test_ipc_ns_shm.rs` 中)

- `unshare(CLONE_NEWIPC)` 后父/子命名空间的 key 不可见;
- 跨命名空间相同 key 不冲突;
- `IPC_RMID` 后可重新创建同 key;
- 输出 PASS/FAIL 与汇总结果。

## 暂未实现/计划中
- `/proc/[pid]/ns/ipc` 与 `setns`:
- 暂缓,仅规划只读占位与最简 `setns` 路径;后续版本补齐权限校验与切换时序。

- SysV IPC 其它子系统:
- `msg/sem` 框架尚未纳入;`sem` 的 UNDO 列表与 `unshare/setns` 的协同需在引入时同步实现。

- POSIX mqueue:
- 尚未提供 per-ns mqueuefs 内核挂载、限额与 sysctl。

- 权限与配额:
- `ipcperms()`、`ns_capable(user_ns, CAP_IPC_OWNER)`;
- ucounts/RLIMIT 与 `/proc/sys/kernel/shm*` 等 per-ns sysctl。

## 兼容性与注意事项
- 当前阶段仅对 SysV SHM 提供命名空间隔离;其它 IPC 类型仍按全局语义工作。
- 代码按模块化方式演进:后续加入 `msg/sem/mqueue` 时,保持对用户侧语义的稳定与一致。

## 参考
- 代码位置:
- `kernel/src/process/namespace/ipc_namespace.rs`
- `kernel/src/process/namespace/nsproxy.rs`
- `kernel/src/ipc/syscall/` 内的 `sys_shm*`
- `kernel/src/mm/ucontext.rs`(VMA 与 SHM 计数维护)


32 changes: 8 additions & 24 deletions kernel/src/ipc/shm.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use crate::{
arch::mm::LockedFrameAllocator,
filesystem::vfs::syscall::ModeType,
libs::{
align::page_align_up,
spinlock::{SpinLock, SpinLockGuard},
},
libs::align::page_align_up,
mm::{
allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
page::{page_manager_lock_irqsave, PageFlags, PageType},
Expand All @@ -15,33 +12,14 @@ use crate::{
time::PosixTimeSpec,
};
use core::fmt;
use core::sync::atomic::{compiler_fence, Ordering};
use hashbrown::HashMap;
use ida::IdAllocator;
use log::info;
use num::ToPrimitive;
use system_error::SystemError;
pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None;

/// 用于创建新的私有IPC对象
pub const IPC_PRIVATE: ShmKey = ShmKey::new(0);

/// 初始化SHM_MANAGER
pub fn shm_manager_init() {
info!("shm_manager_init");
let shm_manager = SpinLock::new(ShmManager::new());

compiler_fence(Ordering::SeqCst);
unsafe { SHM_MANAGER = Some(shm_manager) };
compiler_fence(Ordering::SeqCst);

info!("shm_manager_init done");
}

pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> {
unsafe { SHM_MANAGER.as_ref().unwrap().lock() }
}

int_like!(ShmId, usize);
int_like!(ShmKey, usize);

Expand Down Expand Up @@ -138,6 +116,12 @@ pub struct ShmManager {
key2id: HashMap<ShmKey, ShmId>,
}

impl Default for ShmManager {
fn default() -> Self {
Self::new()
}
}

impl ShmManager {
pub fn new() -> Self {
ShmManager {
Expand Down Expand Up @@ -178,7 +162,7 @@ impl ShmManager {
// 创建共享内存page,并添加到PAGE_MANAGER中
let mut page_manager_guard = page_manager_lock_irqsave();
let (paddr, _page) = page_manager_guard.create_pages(
PageType::Shm(shm_id),
PageType::Shm,
PageFlags::PG_UNEVICTABLE,
&mut LockedFrameAllocator,
page_count,
Expand Down
23 changes: 14 additions & 9 deletions kernel/src/ipc/syscall/sys_shmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ use crate::syscall::table::FormattedSyscallParam;
use crate::{
arch::syscall::nr::SYS_SHMAT,
arch::MMArch,
ipc::shm::{shm_manager_lock, ShmFlags, ShmId},
ipc::shm::{ShmFlags, ShmId},
libs::align::page_align_up,
mm::{
allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
syscall::ProtFlags,
ucontext::{AddressSpace, VMA},
ucontext::{AddressSpace, PhysmapParams, VMA},
VirtAddr, VmFlags,
},
process::ProcessManager,
syscall::{table::Syscall, user_access::UserBufferReader},
};
use syscall_table_macros::declare_syscall;
Expand All @@ -36,7 +37,8 @@ pub(super) fn do_kernel_shmat(
vaddr: VirtAddr,
shmflg: ShmFlags,
) -> Result<usize, SystemError> {
let mut shm_manager_guard = shm_manager_lock();
let ipcns = ProcessManager::current_ipcns();
let mut shm_manager_guard = ipcns.shm.lock();
let current_address_space = AddressSpace::current()?;
let mut address_write_guard = current_address_space.write();

Expand All @@ -59,15 +61,15 @@ pub(super) fn do_kernel_shmat(
let flusher: PageFlushAll<MMArch> = PageFlushAll::new();

// 将共享内存映射到对应虚拟区域
let vma = VMA::physmap(
let params = PhysmapParams {
phys,
destination,
count,
vm_flags,
page_flags,
&mut address_write_guard.user_mapper.utable,
flusher,
)?;
flags: page_flags,
shm_id: Some(id),
};
let vma = VMA::physmap(params, &mut address_write_guard.user_mapper.utable, flusher)?;

// 将VMA加入到当前进程的VMA列表中
address_write_guard.mappings.insert_vma(vma);
Expand Down Expand Up @@ -125,7 +127,10 @@ pub(super) fn do_kernel_shmat(
}

// 更新vma的映射状态
vma.lock_irqsave().set_mapped(true);
let mut vma_guard = vma.lock_irqsave();
vma_guard.set_mapped(true);
vma_guard.set_shm_id(Some(id));
drop(vma_guard);

vaddr.data()
}
Expand Down
7 changes: 5 additions & 2 deletions kernel/src/ipc/syscall/sys_shmctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::alloc::vec::Vec;
use crate::arch::interrupt::TrapFrame;
use crate::{
arch::syscall::nr::SYS_SHMCTL,
ipc::shm::{shm_manager_lock, ShmCtlCmd, ShmId},
ipc::shm::{ShmCtlCmd, ShmId},
process::ProcessManager,
syscall::table::{FormattedSyscallParam, Syscall},
};
use syscall_table_macros::declare_syscall;
Expand All @@ -28,7 +29,9 @@ pub(super) fn do_kernel_shmctl(
user_buf: *const u8,
from_user: bool,
) -> Result<usize, SystemError> {
let mut shm_manager_guard = shm_manager_lock();
// per-ns 管理器
let ipcns = ProcessManager::current_ipcns();
let mut shm_manager_guard = ipcns.shm.lock();

match cmd {
// 查看共享内存元信息
Expand Down
7 changes: 5 additions & 2 deletions kernel/src/ipc/syscall/sys_shmget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::arch::interrupt::TrapFrame;
use crate::syscall::table::FormattedSyscallParam;
use crate::{
arch::syscall::nr::SYS_SHMGET,
ipc::shm::{shm_manager_lock, ShmFlags, ShmKey, IPC_PRIVATE},
ipc::shm::{ShmFlags, ShmKey, IPC_PRIVATE},
process::ProcessManager,
syscall::table::Syscall,
};
use log::error;
Expand Down Expand Up @@ -34,7 +35,9 @@ pub(super) fn do_kernel_shmget(
return Err(SystemError::ENOSYS);
}

let mut shm_manager_guard = shm_manager_lock();
// 从当前进程的 IPC 命名空间获取 per-ns SHM 管理器
let ipcns = ProcessManager::current_ipcns();
let mut shm_manager_guard = ipcns.shm.lock();
match key {
// 创建共享内存段
IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg),
Expand Down
3 changes: 0 additions & 3 deletions kernel/src/mm/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::{
arch::MMArch,
driver::serial::serial8250::send_to_default_serial8250_port,
filesystem::procfs::kmsg::kmsg_init,
ipc::shm::shm_manager_init,
libs::printk::PrintkWriter,
mm::{
allocator::slab::slab_init,
Expand Down Expand Up @@ -59,8 +58,6 @@ pub unsafe fn mm_init() {
kmsg_init();
// enable PAGE_MANAGER
page_manager_init();
// enable SHM_MANAGER
shm_manager_init();
// enable PAGE_RECLAIMER
page_reclaimer_init();

Expand Down
3 changes: 1 addition & 2 deletions kernel/src/mm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::{
exception::ipi::{IpiKind, IpiTarget},
filesystem::{page_cache::PageCache, vfs::FilePrivateData},
init::initcall::INITCALL_CORE,
ipc::shm::ShmId,
libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
Expand Down Expand Up @@ -672,7 +671,7 @@ pub enum PageType {
/// 文件映射页,含文件映射相关信息
File(FileMapInfo),
/// 共享内存页,记录ShmId
Shm(ShmId),
Shm,
}

#[derive(Debug, Clone)]
Expand Down
Loading