1 use crate::{ 2 arch::mm::LockedFrameAllocator, 3 filesystem::vfs::syscall::ModeType, 4 libs::{ 5 align::page_align_up, 6 spinlock::{SpinLock, SpinLockGuard}, 7 }, 8 mm::{ 9 allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame}, 10 page::{page_manager_lock_irqsave, Page}, 11 PhysAddr, 12 }, 13 process::{Pid, ProcessManager}, 14 syscall::user_access::{UserBufferReader, UserBufferWriter}, 15 time::PosixTimeSpec, 16 }; 17 use alloc::vec::Vec; 18 use core::sync::atomic::{compiler_fence, Ordering}; 19 use hashbrown::{HashMap, HashSet}; 20 use ida::IdAllocator; 21 use num::ToPrimitive; 22 use system_error::SystemError; 23 24 pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None; 25 26 /// 用于创建新的私有IPC对象 27 pub const IPC_PRIVATE: ShmKey = ShmKey::new(0); 28 29 /// 初始化SHM_MANAGER 30 pub fn shm_manager_init() { 31 kinfo!("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 kinfo!("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 45 int_like!(ShmId, usize); 46 int_like!(ShmKey, usize); 47 48 bitflags! { 49 pub struct ShmFlags:u32{ 50 const SHM_RDONLY = 0o10000; 51 const SHM_RND = 0o20000; 52 const SHM_REMAP = 0o40000; 53 const SHM_EXEC = 0o100000; 54 const SHM_HUGETLB = 0o4000; 55 56 const IPC_CREAT = 0o1000; 57 const IPC_EXCL = 0o2000; 58 59 const SHM_DEST = 0o1000; 60 const SHM_LOCKED = 0o2000; 61 } 62 } 63 64 /// 管理共享内存段信息的操作码 65 #[derive(Eq, Clone, Copy)] 66 pub enum ShmCtlCmd { 67 /// 删除共享内存段 68 IpcRmid = 0, 69 /// 设置KernIpcPerm选项 70 IpcSet = 1, 71 /// 获取ShmIdDs 72 IpcStat = 2, 73 /// 查看ShmMetaData 74 IpcInfo = 3, 75 76 /// 不允许共享内存段被置换出物理内存 77 ShmLock = 11, 78 /// 允许共享内存段被置换出物理内存 79 ShmUnlock = 12, 80 /// 查看ShmMetaData 81 ShmStat = 13, 82 /// 查看ShmInfo 83 ShmInfo = 14, 84 /// 查看ShmMetaData 85 ShmtStatAny = 15, 86 87 Default, 88 } 89 90 impl From<usize> for ShmCtlCmd { 91 fn from(cmd: usize) -> ShmCtlCmd { 92 match cmd { 93 0 => Self::IpcRmid, 94 1 => Self::IpcSet, 95 2 => Self::IpcStat, 96 3 => Self::IpcInfo, 97 11 => Self::ShmLock, 98 12 => Self::ShmUnlock, 99 13 => Self::ShmStat, 100 14 => Self::ShmInfo, 101 15 => Self::ShmtStatAny, 102 _ => Self::Default, 103 } 104 } 105 } 106 107 impl PartialEq for ShmCtlCmd { 108 fn eq(&self, other: &ShmCtlCmd) -> bool { 109 *self as usize == *other as usize 110 } 111 } 112 113 /// 共享内存管理器 114 #[derive(Debug)] 115 pub struct ShmManager { 116 /// ShmId分配器 117 id_allocator: IdAllocator, 118 /// ShmId映射共享内存信息表 119 id2shm: HashMap<ShmId, KernelShm>, 120 /// ShmKey映射ShmId表 121 key2id: HashMap<ShmKey, ShmId>, 122 } 123 124 impl ShmManager { 125 pub fn new() -> Self { 126 ShmManager { 127 id_allocator: IdAllocator::new(0, usize::MAX - 1), 128 id2shm: HashMap::new(), 129 key2id: HashMap::new(), 130 } 131 } 132 133 /// # 添加共享内存段 134 /// 135 /// ## 参数 136 /// 137 /// - `key`: 共享内存键值 138 /// - `size`: 共享内存大小 139 /// - `shmflg`: 共享内存标志 140 /// 141 /// ## 返回值 142 /// 143 /// 成功:共享内存id 144 /// 失败:对应错误码 145 pub fn add( 146 &mut self, 147 key: ShmKey, 148 size: usize, 149 shmflg: ShmFlags, 150 ) -> Result<usize, SystemError> { 151 // 判断共享内存大小是否过小或溢出 152 if !(PosixShmMetaInfo::SHMMIN..=PosixShmMetaInfo::SHMMAX).contains(&size) { 153 return Err(SystemError::EINVAL); 154 } 155 156 let id = self.id_allocator.alloc().expect("No more id to allocate."); 157 let shm_id = ShmId::new(id); 158 159 // 分配共享内存页面 160 let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap(); 161 let phys_page = 162 unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?; 163 // 创建共享内存page,并添加到PAGE_MANAGER中 164 let mut page_manager_guard = page_manager_lock_irqsave(); 165 let mut cur_phys = PhysPageFrame::new(phys_page.0); 166 for _ in 0..page_count.data() { 167 let mut page = Page::new(true); 168 page.set_shm_id(shm_id); 169 let paddr = cur_phys.phys_address(); 170 page_manager_guard.insert(paddr, page); 171 cur_phys = cur_phys.next(); 172 } 173 174 // 创建共享内存信息结构体 175 let paddr = phys_page.0; 176 let kern_ipc_perm = KernIpcPerm { 177 id: shm_id, 178 key, 179 uid: 0, 180 gid: 0, 181 _cuid: 0, 182 _cgid: 0, 183 mode: shmflg & ShmFlags::from_bits_truncate(ModeType::S_IRWXUGO.bits()), 184 _seq: 0, 185 }; 186 let shm_kernel = KernelShm::new(kern_ipc_perm, paddr, size); 187 188 // 将key、id及其对应KernelShm添加到表中 189 self.id2shm.insert(shm_id, shm_kernel); 190 self.key2id.insert(key, shm_id); 191 192 return Ok(shm_id.data()); 193 } 194 195 pub fn contains_key(&self, key: &ShmKey) -> Option<&ShmId> { 196 self.key2id.get(key) 197 } 198 199 pub fn get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm> { 200 self.id2shm.get_mut(id) 201 } 202 203 pub fn free_key(&mut self, key: &ShmKey) { 204 self.key2id.remove(key); 205 } 206 207 pub fn free_id(&mut self, id: &ShmId) { 208 self.id2shm.remove(id); 209 self.id_allocator.free(id.0); 210 } 211 212 pub fn ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> { 213 let mut user_buffer_writer = UserBufferWriter::new( 214 user_buf as *mut u8, 215 core::mem::size_of::<PosixShmMetaInfo>(), 216 from_user, 217 )?; 218 219 let shm_meta_info = PosixShmMetaInfo::new(); 220 user_buffer_writer.copy_one_to_user(&shm_meta_info, 0)?; 221 222 return Ok(0); 223 } 224 225 pub fn shm_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> { 226 // 已使用id数量 227 let used_ids = self.id2shm.len().to_i32().unwrap(); 228 // 共享内存总和 229 let shm_tot = self.id2shm.iter().fold(0, |acc, (_, kernel_shm)| { 230 acc + PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)) 231 .unwrap() 232 .data() 233 }); 234 let shm_info = PosixShmInfo::new(used_ids, shm_tot, 0, 0, 0, 0); 235 236 let mut user_buffer_writer = UserBufferWriter::new( 237 user_buf as *mut u8, 238 core::mem::size_of::<PosixShmInfo>(), 239 from_user, 240 )?; 241 user_buffer_writer.copy_one_to_user(&shm_info, 0)?; 242 243 return Ok(0); 244 } 245 246 pub fn shm_stat( 247 &self, 248 id: ShmId, 249 cmd: ShmCtlCmd, 250 user_buf: *const u8, 251 from_user: bool, 252 ) -> Result<usize, SystemError> { 253 let kernel_shm = self.id2shm.get(&id).ok_or(SystemError::EINVAL)?; 254 let key = kernel_shm.kern_ipc_perm.key.data().to_i32().unwrap(); 255 let mode = kernel_shm.kern_ipc_perm.mode.bits(); 256 257 let shm_perm = PosixIpcPerm::new(key, 0, 0, 0, 0, mode); 258 let shm_segsz = kernel_shm.shm_size; 259 let shm_atime = kernel_shm.shm_atim.total_nanos(); 260 let shm_dtime = kernel_shm.shm_dtim.total_nanos(); 261 let shm_ctime = kernel_shm.shm_ctim.total_nanos(); 262 let shm_cpid = kernel_shm.shm_cprid.data().to_u32().unwrap(); 263 let shm_lpid = kernel_shm.shm_lprid.data().to_u32().unwrap(); 264 let shm_map_count = kernel_shm.map_count(); 265 let shm_id_ds = PosixShmIdDs { 266 shm_perm, 267 shm_segsz, 268 shm_atime, 269 shm_dtime, 270 shm_ctime, 271 shm_cpid, 272 shm_lpid, 273 shm_map_count, 274 _unused1: 0, 275 _unused2: 0, 276 }; 277 278 let mut user_buffer_writer = UserBufferWriter::new( 279 user_buf as *mut u8, 280 core::mem::size_of::<PosixShmIdDs>(), 281 from_user, 282 )?; 283 user_buffer_writer.copy_one_to_user(&shm_id_ds, 0)?; 284 285 let r: usize = if cmd == ShmCtlCmd::IpcStat { 286 0 287 } else { 288 id.data() 289 }; 290 291 return Ok(r); 292 } 293 294 pub fn ipc_set( 295 &mut self, 296 id: ShmId, 297 user_buf: *const u8, 298 from_user: bool, 299 ) -> Result<usize, SystemError> { 300 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; 301 302 let user_buffer_reader = 303 UserBufferReader::new(user_buf, core::mem::size_of::<PosixShmIdDs>(), from_user)?; 304 let mut shm_id_ds = PosixShmIdDs::default(); 305 user_buffer_reader.copy_one_from_user(&mut shm_id_ds, 0)?; 306 307 kernel_shm.copy_from(shm_id_ds); 308 309 return Ok(0); 310 } 311 312 pub fn ipc_rmid(&mut self, id: ShmId) -> Result<usize, SystemError> { 313 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; 314 kernel_shm.set_mode(ShmFlags::SHM_DEST, true); 315 316 let mut cur_phys = PhysPageFrame::new(kernel_shm.shm_start_paddr); 317 let count = PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)).unwrap(); 318 let key = kernel_shm.kern_ipc_perm.key; 319 let id = kernel_shm.kern_ipc_perm.id; 320 let map_count = kernel_shm.map_count(); 321 322 let mut page_manager_guard = page_manager_lock_irqsave(); 323 if map_count > 0 { 324 // 设置共享内存物理页当映射计数等于0时可被回收 325 for _ in 0..count.data() { 326 let page = page_manager_guard.get_mut(&cur_phys.phys_address()); 327 page.set_dealloc_when_zero(true); 328 329 cur_phys = cur_phys.next(); 330 } 331 332 // 释放key,不让后续进程连接 333 self.free_key(&key); 334 } else { 335 // 释放共享内存物理页 336 for _ in 0..count.data() { 337 let paddr = cur_phys.phys_address(); 338 unsafe { 339 LockedFrameAllocator.free(paddr, PageFrameCount::new(1)); 340 } 341 // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去 342 page_manager_guard.remove_page(&paddr); 343 cur_phys = cur_phys.next(); 344 } 345 346 // 释放key和id 347 self.free_id(&id); 348 self.free_key(&key) 349 } 350 351 return Ok(0); 352 } 353 354 pub fn shm_lock(&mut self, id: ShmId) -> Result<usize, SystemError> { 355 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; 356 kernel_shm.set_mode(ShmFlags::SHM_LOCKED, true); 357 358 return Ok(0); 359 } 360 361 pub fn shm_unlock(&mut self, id: ShmId) -> Result<usize, SystemError> { 362 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; 363 kernel_shm.set_mode(ShmFlags::SHM_LOCKED, false); 364 365 return Ok(0); 366 } 367 } 368 /// 共享内存信息 369 #[derive(Debug)] 370 pub struct KernelShm { 371 /// 权限信息 372 kern_ipc_perm: KernIpcPerm, 373 /// 共享内存起始物理地址 374 shm_start_paddr: PhysAddr, 375 /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐) 376 shm_size: usize, 377 /// 最后一次连接的时间 378 shm_atim: PosixTimeSpec, 379 /// 最后一次断开连接的时间 380 shm_dtim: PosixTimeSpec, 381 /// 最后一次更改信息的时间 382 shm_ctim: PosixTimeSpec, 383 /// 创建者进程id 384 shm_cprid: Pid, 385 /// 最后操作者进程id 386 shm_lprid: Pid, 387 } 388 389 impl KernelShm { 390 pub fn new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self { 391 let shm_cprid = ProcessManager::current_pid(); 392 KernelShm { 393 kern_ipc_perm, 394 shm_start_paddr, 395 shm_size, 396 shm_atim: PosixTimeSpec::new(0, 0), 397 shm_dtim: PosixTimeSpec::new(0, 0), 398 shm_ctim: PosixTimeSpec::now(), 399 shm_cprid, 400 shm_lprid: shm_cprid, 401 } 402 } 403 404 pub fn start_paddr(&self) -> PhysAddr { 405 self.shm_start_paddr 406 } 407 408 pub fn size(&self) -> usize { 409 self.shm_size 410 } 411 412 /// 更新最后连接时间 413 pub fn update_atim(&mut self) { 414 // 更新最后一次连接时间 415 self.shm_atim = PosixTimeSpec::now(); 416 417 // 更新最后操作当前共享内存的进程ID 418 self.shm_lprid = ProcessManager::current_pid(); 419 } 420 421 /// 更新最后断开连接时间 422 pub fn update_dtim(&mut self) { 423 // 更新最后一次断开连接时间 424 self.shm_dtim = PosixTimeSpec::now(); 425 426 // 更新最后操作当前共享内存的进程ID 427 self.shm_lprid = ProcessManager::current_pid(); 428 } 429 430 /// 更新最后一次修改信息的时间 431 pub fn update_ctim(&mut self) { 432 // 更新最后一次修改信息的时间 433 self.shm_ctim = PosixTimeSpec::now(); 434 } 435 436 /// 共享内存段的映射计数(有多少个不同的VMA映射) 437 pub fn map_count(&self) -> usize { 438 let page_manager_guard = page_manager_lock_irqsave(); 439 let mut id_set: HashSet<usize> = HashSet::new(); 440 let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr); 441 let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap(); 442 443 for _ in 0..page_count.data() { 444 let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap(); 445 id_set.extend( 446 page.anon_vma() 447 .iter() 448 .map(|vma| vma.id()) 449 .collect::<Vec<_>>(), 450 ); 451 452 cur_phys = cur_phys.next(); 453 } 454 455 // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段 456 return id_set.len(); 457 } 458 459 pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) { 460 self.kern_ipc_perm.uid = shm_id_ds.uid() as usize; 461 self.kern_ipc_perm.gid = shm_id_ds.gid() as usize; 462 self.kern_ipc_perm.mode = ShmFlags::from_bits_truncate(shm_id_ds.mode()); 463 self.update_ctim(); 464 } 465 466 pub fn set_mode(&mut self, shmflg: ShmFlags, set: bool) { 467 if set { 468 self.kern_ipc_perm.mode.insert(shmflg); 469 } else { 470 self.kern_ipc_perm.mode.remove(shmflg); 471 } 472 473 self.update_ctim(); 474 } 475 } 476 477 /// 共享内存权限信息 478 #[derive(Debug)] 479 pub struct KernIpcPerm { 480 /// 共享内存id 481 id: ShmId, 482 /// 共享内存键值,由创建共享内存用户指定 483 key: ShmKey, 484 /// 共享内存拥有者用户id 485 uid: usize, 486 /// 共享内存拥有者所在组id 487 gid: usize, 488 /// 共享内存创建者用户id 489 _cuid: usize, 490 /// 共享内存创建者所在组id 491 _cgid: usize, 492 /// 共享内存区权限模式 493 mode: ShmFlags, 494 _seq: usize, 495 } 496 497 /// 共享内存元信息,符合POSIX标准 498 #[repr(C)] 499 #[derive(Debug, Clone, Copy)] 500 pub struct PosixShmMetaInfo { 501 /// 最大共享内存段的大小(bytes) 502 shmmax: usize, 503 /// 最小共享内存段的大小(bytes) 504 shmmin: usize, 505 /// 最大共享内存标识符数量 506 shmmni: usize, 507 /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同 508 shmseg: usize, 509 /// 所有共享内存段总共可以使用的最大内存量(pages) 510 shmall: usize, 511 _unused1: usize, 512 _unused2: usize, 513 _unused3: usize, 514 _unused4: usize, 515 } 516 517 impl PosixShmMetaInfo { 518 /// 最小共享内存段的大小(bytes) 519 pub const SHMMIN: usize = 1; 520 /// 最大共享内存标识符数量 521 pub const SHMMNI: usize = 4096; 522 /// 最大共享内存段的大小(bytes) 523 pub const SHMMAX: usize = usize::MAX - (1 << 24); 524 /// 所有共享内存段总共可以使用的最大内存量(pages) 525 pub const SHMALL: usize = usize::MAX - (1 << 24); 526 /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同 527 pub const SHMSEG: usize = 4096; 528 529 pub fn new() -> Self { 530 PosixShmMetaInfo { 531 shmmax: Self::SHMMAX, 532 shmmin: Self::SHMMIN, 533 shmmni: Self::SHMMNI, 534 shmseg: Self::SHMSEG, 535 shmall: Self::SHMALL, 536 _unused1: 0, 537 _unused2: 0, 538 _unused3: 0, 539 _unused4: 0, 540 } 541 } 542 } 543 544 /// 共享内存信息,符合POSIX标准 545 #[repr(C)] 546 #[derive(Clone, Copy)] 547 pub struct PosixShmInfo { 548 /// 已使用id数 549 used_ids: i32, 550 /// 共享内存总量(pages) 551 shm_tot: usize, 552 /// 保留在内存中的共享内存大小 553 shm_rss: usize, 554 /// 被置换出的共享内存大小 555 shm_swp: usize, 556 /// 尝试置换次数 557 swap_attempts: usize, 558 /// 成功置换次数 559 swap_successes: usize, 560 } 561 562 impl PosixShmInfo { 563 pub fn new( 564 used_ids: i32, 565 shm_tot: usize, 566 shm_rss: usize, 567 shm_swp: usize, 568 swap_attempts: usize, 569 swap_successes: usize, 570 ) -> Self { 571 PosixShmInfo { 572 used_ids, 573 shm_tot, 574 shm_rss, 575 shm_swp, 576 swap_attempts, 577 swap_successes, 578 } 579 } 580 } 581 582 /// 共享内存段属性信息,符合POSIX标准 583 #[repr(C)] 584 #[derive(Debug, Clone, Copy, Default)] 585 pub struct PosixShmIdDs { 586 /// 共享内存段权限 587 shm_perm: PosixIpcPerm, 588 /// 共享内存大小(bytes) 589 shm_segsz: usize, 590 /// 最后一次连接的时间 591 shm_atime: i64, 592 /// 最后一次断开连接的时间 593 shm_dtime: i64, 594 /// 最后一次更改信息的时间 595 shm_ctime: i64, 596 /// 创建者进程id 597 shm_cpid: u32, 598 /// 最后操作者进程id 599 shm_lpid: u32, 600 /// 链接数 601 shm_map_count: usize, 602 _unused1: usize, 603 _unused2: usize, 604 } 605 606 impl PosixShmIdDs { 607 pub fn uid(&self) -> u32 { 608 self.shm_perm.uid 609 } 610 611 pub fn gid(&self) -> u32 { 612 self.shm_perm.gid 613 } 614 615 pub fn mode(&self) -> u32 { 616 self.shm_perm.mode 617 } 618 } 619 620 /// 共享内存段权限,符合POSIX标准 621 #[repr(C)] 622 #[derive(Debug, Clone, Copy, Default)] 623 pub struct PosixIpcPerm { 624 /// IPC对象键值 625 key: i32, 626 /// 当前用户id 627 uid: u32, 628 /// 当前用户组id 629 gid: u32, 630 /// 创建者用户id 631 cuid: u32, 632 /// 创建者组id 633 cgid: u32, 634 /// 权限 635 mode: u32, 636 /// 序列号 637 seq: i32, 638 _pad1: i32, 639 _unused1: usize, 640 _unused2: usize, 641 } 642 643 impl PosixIpcPerm { 644 pub fn new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self { 645 PosixIpcPerm { 646 key, 647 uid, 648 gid, 649 cuid, 650 cgid, 651 mode, 652 seq: 0, 653 _pad1: 0, 654 _unused1: 0, 655 _unused2: 0, 656 } 657 } 658 } 659