Skip to content

Commit ef296a3

Browse files
authored
feat(ipc): 实现IPC命名空间初步支持 (#1288)
* feat(ipc): 实现IPC命名空间第一阶段支持 - 添加IpcNamespace结构体并集成到NsProxy中 - 将全局SHM_MANAGER重构为per-ns ShmManager - 修改shm相关系统调用以支持命名空间隔离 - 添加VMA的shm_id字段用于精确维护映射计数 - 新增IPC命名空间测试用例 - 更新相关文档 Signed-off-by: longjin <[email protected]> * fmt Signed-off-by: longjin <[email protected]> --------- Signed-off-by: longjin <[email protected]>
1 parent 509ee34 commit ef296a3

File tree

14 files changed

+452
-304
lines changed

14 files changed

+452
-304
lines changed

docs/kernel/ipc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
:maxdepth: 1
99

1010
signal
11+
ipc_namespace

docs/kernel/ipc/ipc_namespace.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# IPC Namespace
2+
3+
:::{note}
4+
5+
Author: longjin <[email protected]>
6+
7+
:::
8+
9+
本页描述 DragonOS 对 IPC 命名空间(IPC namespace)的当前支持状态与后续计划。目标是对用户暴露与 Linux 一致的语义,并在 DragonOS 现有框架上逐步完善。
10+
11+
## 已支持功能
12+
- IpcNamespace 对象与 NsProxy 集成:
13+
- 新增 `IpcNamespace` 并接入 `NsProxy`,每个任务通过 `nsproxy.ipc_ns` 访问所属 IPC 命名空间。
14+
- 命名空间的创建/继承遵循 `clone/unshare` 语义:
15+
- 未包含 `CLONE_NEWIPC` 时继承父命名空间;
16+
- 包含 `CLONE_NEWIPC` 时创建独立 IPC 命名空间;
17+
-`CLONE_SYSVSEM` 互斥,行为与 Linux 一致。
18+
19+
- SysV SHM(共享内存)按命名空间隔离:
20+
- 将原全局 `SHM_MANAGER` 重构为 per-ns `ShmManager`,所有 `shmget/shmat/shmdt/shmctl` 均在 `current.nsproxy.ipc_ns` 下生效。
21+
- `shmat`/`shmdt`:VMA 记录 `ShmId`,解除映射时精确维护 `map_count``IPC_RMID` 后当 `SHM_DEST && map_count==0` 即完成物理回收。
22+
- 基本语义与错误码对齐:`IPC_CREAT|IPC_EXCL``ENOENT`、拒绝 `SHM_HUGETLB` 等。
23+
24+
- 基础测试用例:(在 `test_ipc_ns_shm.rs` 中)
25+
26+
- `unshare(CLONE_NEWIPC)` 后父/子命名空间的 key 不可见;
27+
- 跨命名空间相同 key 不冲突;
28+
- `IPC_RMID` 后可重新创建同 key;
29+
- 输出 PASS/FAIL 与汇总结果。
30+
31+
## 暂未实现/计划中
32+
- `/proc/[pid]/ns/ipc``setns`
33+
- 暂缓,仅规划只读占位与最简 `setns` 路径;后续版本补齐权限校验与切换时序。
34+
35+
- SysV IPC 其它子系统:
36+
- `msg/sem` 框架尚未纳入;`sem` 的 UNDO 列表与 `unshare/setns` 的协同需在引入时同步实现。
37+
38+
- POSIX mqueue:
39+
- 尚未提供 per-ns mqueuefs 内核挂载、限额与 sysctl。
40+
41+
- 权限与配额:
42+
- `ipcperms()``ns_capable(user_ns, CAP_IPC_OWNER)`
43+
- ucounts/RLIMIT 与 `/proc/sys/kernel/shm*` 等 per-ns sysctl。
44+
45+
## 兼容性与注意事项
46+
- 当前阶段仅对 SysV SHM 提供命名空间隔离;其它 IPC 类型仍按全局语义工作。
47+
- 代码按模块化方式演进:后续加入 `msg/sem/mqueue` 时,保持对用户侧语义的稳定与一致。
48+
49+
## 参考
50+
- 代码位置:
51+
- `kernel/src/process/namespace/ipc_namespace.rs`
52+
- `kernel/src/process/namespace/nsproxy.rs`
53+
- `kernel/src/ipc/syscall/` 内的 `sys_shm*`
54+
- `kernel/src/mm/ucontext.rs`(VMA 与 SHM 计数维护)
55+
56+

kernel/src/ipc/shm.rs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use crate::{
22
arch::mm::LockedFrameAllocator,
33
filesystem::vfs::syscall::ModeType,
4-
libs::{
5-
align::page_align_up,
6-
spinlock::{SpinLock, SpinLockGuard},
7-
},
4+
libs::align::page_align_up,
85
mm::{
96
allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
107
page::{page_manager_lock_irqsave, PageFlags, PageType},
@@ -15,33 +12,14 @@ use crate::{
1512
time::PosixTimeSpec,
1613
};
1714
use core::fmt;
18-
use core::sync::atomic::{compiler_fence, Ordering};
1915
use hashbrown::HashMap;
2016
use ida::IdAllocator;
21-
use log::info;
2217
use num::ToPrimitive;
2318
use system_error::SystemError;
24-
pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None;
2519

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

29-
/// 初始化SHM_MANAGER
30-
pub fn shm_manager_init() {
31-
info!("shm_manager_init");
32-
let shm_manager = SpinLock::new(ShmManager::new());
33-
34-
compiler_fence(Ordering::SeqCst);
35-
unsafe { SHM_MANAGER = Some(shm_manager) };
36-
compiler_fence(Ordering::SeqCst);
37-
38-
info!("shm_manager_init done");
39-
}
40-
41-
pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> {
42-
unsafe { SHM_MANAGER.as_ref().unwrap().lock() }
43-
}
44-
4523
int_like!(ShmId, usize);
4624
int_like!(ShmKey, usize);
4725

@@ -138,6 +116,12 @@ pub struct ShmManager {
138116
key2id: HashMap<ShmKey, ShmId>,
139117
}
140118

119+
impl Default for ShmManager {
120+
fn default() -> Self {
121+
Self::new()
122+
}
123+
}
124+
141125
impl ShmManager {
142126
pub fn new() -> Self {
143127
ShmManager {
@@ -178,7 +162,7 @@ impl ShmManager {
178162
// 创建共享内存page,并添加到PAGE_MANAGER中
179163
let mut page_manager_guard = page_manager_lock_irqsave();
180164
let (paddr, _page) = page_manager_guard.create_pages(
181-
PageType::Shm(shm_id),
165+
PageType::Shm,
182166
PageFlags::PG_UNEVICTABLE,
183167
&mut LockedFrameAllocator,
184168
page_count,

kernel/src/ipc/syscall/sys_shmat.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ use crate::syscall::table::FormattedSyscallParam;
44
use crate::{
55
arch::syscall::nr::SYS_SHMAT,
66
arch::MMArch,
7-
ipc::shm::{shm_manager_lock, ShmFlags, ShmId},
7+
ipc::shm::{ShmFlags, ShmId},
88
libs::align::page_align_up,
99
mm::{
1010
allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
1111
page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
1212
syscall::ProtFlags,
13-
ucontext::{AddressSpace, VMA},
13+
ucontext::{AddressSpace, PhysmapParams, VMA},
1414
VirtAddr, VmFlags,
1515
},
16+
process::ProcessManager,
1617
syscall::{table::Syscall, user_access::UserBufferReader},
1718
};
1819
use syscall_table_macros::declare_syscall;
@@ -36,7 +37,8 @@ pub(super) fn do_kernel_shmat(
3637
vaddr: VirtAddr,
3738
shmflg: ShmFlags,
3839
) -> Result<usize, SystemError> {
39-
let mut shm_manager_guard = shm_manager_lock();
40+
let ipcns = ProcessManager::current_ipcns();
41+
let mut shm_manager_guard = ipcns.shm.lock();
4042
let current_address_space = AddressSpace::current()?;
4143
let mut address_write_guard = current_address_space.write();
4244

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

6163
// 将共享内存映射到对应虚拟区域
62-
let vma = VMA::physmap(
64+
let params = PhysmapParams {
6365
phys,
6466
destination,
6567
count,
6668
vm_flags,
67-
page_flags,
68-
&mut address_write_guard.user_mapper.utable,
69-
flusher,
70-
)?;
69+
flags: page_flags,
70+
shm_id: Some(id),
71+
};
72+
let vma = VMA::physmap(params, &mut address_write_guard.user_mapper.utable, flusher)?;
7173

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

127129
// 更新vma的映射状态
128-
vma.lock_irqsave().set_mapped(true);
130+
let mut vma_guard = vma.lock_irqsave();
131+
vma_guard.set_mapped(true);
132+
vma_guard.set_shm_id(Some(id));
133+
drop(vma_guard);
129134

130135
vaddr.data()
131136
}

kernel/src/ipc/syscall/sys_shmctl.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::alloc::vec::Vec;
22
use crate::arch::interrupt::TrapFrame;
33
use crate::{
44
arch::syscall::nr::SYS_SHMCTL,
5-
ipc::shm::{shm_manager_lock, ShmCtlCmd, ShmId},
5+
ipc::shm::{ShmCtlCmd, ShmId},
6+
process::ProcessManager,
67
syscall::table::{FormattedSyscallParam, Syscall},
78
};
89
use syscall_table_macros::declare_syscall;
@@ -28,7 +29,9 @@ pub(super) fn do_kernel_shmctl(
2829
user_buf: *const u8,
2930
from_user: bool,
3031
) -> Result<usize, SystemError> {
31-
let mut shm_manager_guard = shm_manager_lock();
32+
// per-ns 管理器
33+
let ipcns = ProcessManager::current_ipcns();
34+
let mut shm_manager_guard = ipcns.shm.lock();
3235

3336
match cmd {
3437
// 查看共享内存元信息

kernel/src/ipc/syscall/sys_shmget.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use crate::arch::interrupt::TrapFrame;
33
use crate::syscall::table::FormattedSyscallParam;
44
use crate::{
55
arch::syscall::nr::SYS_SHMGET,
6-
ipc::shm::{shm_manager_lock, ShmFlags, ShmKey, IPC_PRIVATE},
6+
ipc::shm::{ShmFlags, ShmKey, IPC_PRIVATE},
7+
process::ProcessManager,
78
syscall::table::Syscall,
89
};
910
use log::error;
@@ -34,7 +35,9 @@ pub(super) fn do_kernel_shmget(
3435
return Err(SystemError::ENOSYS);
3536
}
3637

37-
let mut shm_manager_guard = shm_manager_lock();
38+
// 从当前进程的 IPC 命名空间获取 per-ns SHM 管理器
39+
let ipcns = ProcessManager::current_ipcns();
40+
let mut shm_manager_guard = ipcns.shm.lock();
3841
match key {
3942
// 创建共享内存段
4043
IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg),

kernel/src/mm/init.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::{
66
arch::MMArch,
77
driver::serial::serial8250::send_to_default_serial8250_port,
88
filesystem::procfs::kmsg::kmsg_init,
9-
ipc::shm::shm_manager_init,
109
libs::printk::PrintkWriter,
1110
mm::{
1211
allocator::slab::slab_init,
@@ -59,8 +58,6 @@ pub unsafe fn mm_init() {
5958
kmsg_init();
6059
// enable PAGE_MANAGER
6160
page_manager_init();
62-
// enable SHM_MANAGER
63-
shm_manager_init();
6461
// enable PAGE_RECLAIMER
6562
page_reclaimer_init();
6663

kernel/src/mm/page.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::{
1919
exception::ipi::{IpiKind, IpiTarget},
2020
filesystem::{page_cache::PageCache, vfs::FilePrivateData},
2121
init::initcall::INITCALL_CORE,
22-
ipc::shm::ShmId,
2322
libs::{
2423
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
2524
spinlock::{SpinLock, SpinLockGuard},
@@ -672,7 +671,7 @@ pub enum PageType {
672671
/// 文件映射页,含文件映射相关信息
673672
File(FileMapInfo),
674673
/// 共享内存页,记录ShmId
675-
Shm(ShmId),
674+
Shm,
676675
}
677676

678677
#[derive(Debug, Clone)]

0 commit comments

Comments
 (0)