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