xref: /DragonOS/kernel/src/ipc/shm.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
16fc066acSJomo use crate::{
26fc066acSJomo     arch::mm::LockedFrameAllocator,
36fc066acSJomo     filesystem::vfs::syscall::ModeType,
46fc066acSJomo     libs::{
56fc066acSJomo         align::page_align_up,
66fc066acSJomo         spinlock::{SpinLock, SpinLockGuard},
76fc066acSJomo     },
86fc066acSJomo     mm::{
96fc066acSJomo         allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
106fc066acSJomo         page::{page_manager_lock_irqsave, Page},
116fc066acSJomo         PhysAddr,
126fc066acSJomo     },
136fc066acSJomo     process::{Pid, ProcessManager},
146fc066acSJomo     syscall::user_access::{UserBufferReader, UserBufferWriter},
156fc066acSJomo     time::PosixTimeSpec,
166fc066acSJomo };
176fc066acSJomo use alloc::vec::Vec;
186fc066acSJomo use core::sync::atomic::{compiler_fence, Ordering};
196fc066acSJomo use hashbrown::{HashMap, HashSet};
206fc066acSJomo use ida::IdAllocator;
21*2eab6dd7S曾俊 use log::info;
226fc066acSJomo use num::ToPrimitive;
236fc066acSJomo use system_error::SystemError;
246fc066acSJomo 
256fc066acSJomo pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None;
266fc066acSJomo 
276fc066acSJomo /// 用于创建新的私有IPC对象
286fc066acSJomo pub const IPC_PRIVATE: ShmKey = ShmKey::new(0);
296fc066acSJomo 
306fc066acSJomo /// 初始化SHM_MANAGER
316fc066acSJomo pub fn shm_manager_init() {
32*2eab6dd7S曾俊     info!("shm_manager_init");
336fc066acSJomo     let shm_manager = SpinLock::new(ShmManager::new());
346fc066acSJomo 
356fc066acSJomo     compiler_fence(Ordering::SeqCst);
366fc066acSJomo     unsafe { SHM_MANAGER = Some(shm_manager) };
376fc066acSJomo     compiler_fence(Ordering::SeqCst);
386fc066acSJomo 
39*2eab6dd7S曾俊     info!("shm_manager_init done");
406fc066acSJomo }
416fc066acSJomo 
426fc066acSJomo pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> {
436fc066acSJomo     unsafe { SHM_MANAGER.as_ref().unwrap().lock() }
446fc066acSJomo }
456fc066acSJomo 
466fc066acSJomo int_like!(ShmId, usize);
476fc066acSJomo int_like!(ShmKey, usize);
486fc066acSJomo 
496fc066acSJomo bitflags! {
506fc066acSJomo     pub struct ShmFlags:u32{
516fc066acSJomo         const SHM_RDONLY = 0o10000;
526fc066acSJomo         const SHM_RND = 0o20000;
536fc066acSJomo         const SHM_REMAP = 0o40000;
546fc066acSJomo         const SHM_EXEC = 0o100000;
556fc066acSJomo         const SHM_HUGETLB = 0o4000;
566fc066acSJomo 
576fc066acSJomo         const IPC_CREAT = 0o1000;
586fc066acSJomo         const IPC_EXCL = 0o2000;
596fc066acSJomo 
606fc066acSJomo         const SHM_DEST = 0o1000;
616fc066acSJomo         const SHM_LOCKED = 0o2000;
626fc066acSJomo     }
636fc066acSJomo }
646fc066acSJomo 
656fc066acSJomo /// 管理共享内存段信息的操作码
666fc066acSJomo #[derive(Eq, Clone, Copy)]
676fc066acSJomo pub enum ShmCtlCmd {
686fc066acSJomo     /// 删除共享内存段
696fc066acSJomo     IpcRmid = 0,
706fc066acSJomo     /// 设置KernIpcPerm选项
716fc066acSJomo     IpcSet = 1,
726fc066acSJomo     /// 获取ShmIdDs
736fc066acSJomo     IpcStat = 2,
746fc066acSJomo     /// 查看ShmMetaData
756fc066acSJomo     IpcInfo = 3,
766fc066acSJomo 
776fc066acSJomo     /// 不允许共享内存段被置换出物理内存
786fc066acSJomo     ShmLock = 11,
796fc066acSJomo     /// 允许共享内存段被置换出物理内存
806fc066acSJomo     ShmUnlock = 12,
816fc066acSJomo     /// 查看ShmMetaData
826fc066acSJomo     ShmStat = 13,
836fc066acSJomo     /// 查看ShmInfo
846fc066acSJomo     ShmInfo = 14,
856fc066acSJomo     /// 查看ShmMetaData
866fc066acSJomo     ShmtStatAny = 15,
876fc066acSJomo 
886fc066acSJomo     Default,
896fc066acSJomo }
906fc066acSJomo 
916fc066acSJomo impl From<usize> for ShmCtlCmd {
926fc066acSJomo     fn from(cmd: usize) -> ShmCtlCmd {
936fc066acSJomo         match cmd {
946fc066acSJomo             0 => Self::IpcRmid,
956fc066acSJomo             1 => Self::IpcSet,
966fc066acSJomo             2 => Self::IpcStat,
976fc066acSJomo             3 => Self::IpcInfo,
986fc066acSJomo             11 => Self::ShmLock,
996fc066acSJomo             12 => Self::ShmUnlock,
1006fc066acSJomo             13 => Self::ShmStat,
1016fc066acSJomo             14 => Self::ShmInfo,
1026fc066acSJomo             15 => Self::ShmtStatAny,
1036fc066acSJomo             _ => Self::Default,
1046fc066acSJomo         }
1056fc066acSJomo     }
1066fc066acSJomo }
1076fc066acSJomo 
1086fc066acSJomo impl PartialEq for ShmCtlCmd {
1096fc066acSJomo     fn eq(&self, other: &ShmCtlCmd) -> bool {
1106fc066acSJomo         *self as usize == *other as usize
1116fc066acSJomo     }
1126fc066acSJomo }
1136fc066acSJomo 
1146fc066acSJomo /// 共享内存管理器
1156fc066acSJomo #[derive(Debug)]
1166fc066acSJomo pub struct ShmManager {
1176fc066acSJomo     /// ShmId分配器
1186fc066acSJomo     id_allocator: IdAllocator,
1196fc066acSJomo     /// ShmId映射共享内存信息表
1206fc066acSJomo     id2shm: HashMap<ShmId, KernelShm>,
1216fc066acSJomo     /// ShmKey映射ShmId表
1226fc066acSJomo     key2id: HashMap<ShmKey, ShmId>,
1236fc066acSJomo }
1246fc066acSJomo 
1256fc066acSJomo impl ShmManager {
1266fc066acSJomo     pub fn new() -> Self {
1276fc066acSJomo         ShmManager {
1286fc066acSJomo             id_allocator: IdAllocator::new(0, usize::MAX - 1),
1296fc066acSJomo             id2shm: HashMap::new(),
1306fc066acSJomo             key2id: HashMap::new(),
1316fc066acSJomo         }
1326fc066acSJomo     }
1336fc066acSJomo 
1346fc066acSJomo     /// # 添加共享内存段
1356fc066acSJomo     ///
1366fc066acSJomo     /// ## 参数
1376fc066acSJomo     ///
1386fc066acSJomo     /// - `key`: 共享内存键值
1396fc066acSJomo     /// - `size`: 共享内存大小
1406fc066acSJomo     /// - `shmflg`: 共享内存标志
1416fc066acSJomo     ///
1426fc066acSJomo     /// ## 返回值
1436fc066acSJomo     ///
1446fc066acSJomo     /// 成功:共享内存id
1456fc066acSJomo     /// 失败:对应错误码
1466fc066acSJomo     pub fn add(
1476fc066acSJomo         &mut self,
1486fc066acSJomo         key: ShmKey,
1496fc066acSJomo         size: usize,
1506fc066acSJomo         shmflg: ShmFlags,
1516fc066acSJomo     ) -> Result<usize, SystemError> {
1526fc066acSJomo         // 判断共享内存大小是否过小或溢出
1536fc066acSJomo         if !(PosixShmMetaInfo::SHMMIN..=PosixShmMetaInfo::SHMMAX).contains(&size) {
1546fc066acSJomo             return Err(SystemError::EINVAL);
1556fc066acSJomo         }
1566fc066acSJomo 
1576fc066acSJomo         let id = self.id_allocator.alloc().expect("No more id to allocate.");
1586fc066acSJomo         let shm_id = ShmId::new(id);
1596fc066acSJomo 
1606fc066acSJomo         // 分配共享内存页面
1616fc066acSJomo         let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap();
1626fc066acSJomo         let phys_page =
1636fc066acSJomo             unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?;
1646fc066acSJomo         // 创建共享内存page,并添加到PAGE_MANAGER中
1656fc066acSJomo         let mut page_manager_guard = page_manager_lock_irqsave();
1666fc066acSJomo         let mut cur_phys = PhysPageFrame::new(phys_page.0);
1676fc066acSJomo         for _ in 0..page_count.data() {
1686fc066acSJomo             let mut page = Page::new(true);
1696fc066acSJomo             page.set_shm_id(shm_id);
1706fc066acSJomo             let paddr = cur_phys.phys_address();
1716fc066acSJomo             page_manager_guard.insert(paddr, page);
1726fc066acSJomo             cur_phys = cur_phys.next();
1736fc066acSJomo         }
1746fc066acSJomo 
1756fc066acSJomo         // 创建共享内存信息结构体
1766fc066acSJomo         let paddr = phys_page.0;
1776fc066acSJomo         let kern_ipc_perm = KernIpcPerm {
1786fc066acSJomo             id: shm_id,
1796fc066acSJomo             key,
1806fc066acSJomo             uid: 0,
1816fc066acSJomo             gid: 0,
1826fc066acSJomo             _cuid: 0,
1836fc066acSJomo             _cgid: 0,
1846fc066acSJomo             mode: shmflg & ShmFlags::from_bits_truncate(ModeType::S_IRWXUGO.bits()),
1856fc066acSJomo             _seq: 0,
1866fc066acSJomo         };
1876fc066acSJomo         let shm_kernel = KernelShm::new(kern_ipc_perm, paddr, size);
1886fc066acSJomo 
1896fc066acSJomo         // 将key、id及其对应KernelShm添加到表中
1906fc066acSJomo         self.id2shm.insert(shm_id, shm_kernel);
1916fc066acSJomo         self.key2id.insert(key, shm_id);
1926fc066acSJomo 
1936fc066acSJomo         return Ok(shm_id.data());
1946fc066acSJomo     }
1956fc066acSJomo 
1966fc066acSJomo     pub fn contains_key(&self, key: &ShmKey) -> Option<&ShmId> {
1976fc066acSJomo         self.key2id.get(key)
1986fc066acSJomo     }
1996fc066acSJomo 
2006fc066acSJomo     pub fn get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm> {
2016fc066acSJomo         self.id2shm.get_mut(id)
2026fc066acSJomo     }
2036fc066acSJomo 
2046fc066acSJomo     pub fn free_key(&mut self, key: &ShmKey) {
2056fc066acSJomo         self.key2id.remove(key);
2066fc066acSJomo     }
2076fc066acSJomo 
2086fc066acSJomo     pub fn free_id(&mut self, id: &ShmId) {
2096fc066acSJomo         self.id2shm.remove(id);
2106fc066acSJomo         self.id_allocator.free(id.0);
2116fc066acSJomo     }
2126fc066acSJomo 
2136fc066acSJomo     pub fn ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
2146fc066acSJomo         let mut user_buffer_writer = UserBufferWriter::new(
2156fc066acSJomo             user_buf as *mut u8,
2166fc066acSJomo             core::mem::size_of::<PosixShmMetaInfo>(),
2176fc066acSJomo             from_user,
2186fc066acSJomo         )?;
2196fc066acSJomo 
2206fc066acSJomo         let shm_meta_info = PosixShmMetaInfo::new();
2216fc066acSJomo         user_buffer_writer.copy_one_to_user(&shm_meta_info, 0)?;
2226fc066acSJomo 
2236fc066acSJomo         return Ok(0);
2246fc066acSJomo     }
2256fc066acSJomo 
2266fc066acSJomo     pub fn shm_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
2276fc066acSJomo         // 已使用id数量
2286fc066acSJomo         let used_ids = self.id2shm.len().to_i32().unwrap();
2296fc066acSJomo         // 共享内存总和
2306fc066acSJomo         let shm_tot = self.id2shm.iter().fold(0, |acc, (_, kernel_shm)| {
2316fc066acSJomo             acc + PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size))
2326fc066acSJomo                 .unwrap()
2336fc066acSJomo                 .data()
2346fc066acSJomo         });
2356fc066acSJomo         let shm_info = PosixShmInfo::new(used_ids, shm_tot, 0, 0, 0, 0);
2366fc066acSJomo 
2376fc066acSJomo         let mut user_buffer_writer = UserBufferWriter::new(
2386fc066acSJomo             user_buf as *mut u8,
2396fc066acSJomo             core::mem::size_of::<PosixShmInfo>(),
2406fc066acSJomo             from_user,
2416fc066acSJomo         )?;
2426fc066acSJomo         user_buffer_writer.copy_one_to_user(&shm_info, 0)?;
2436fc066acSJomo 
2446fc066acSJomo         return Ok(0);
2456fc066acSJomo     }
2466fc066acSJomo 
2476fc066acSJomo     pub fn shm_stat(
2486fc066acSJomo         &self,
2496fc066acSJomo         id: ShmId,
2506fc066acSJomo         cmd: ShmCtlCmd,
2516fc066acSJomo         user_buf: *const u8,
2526fc066acSJomo         from_user: bool,
2536fc066acSJomo     ) -> Result<usize, SystemError> {
2546fc066acSJomo         let kernel_shm = self.id2shm.get(&id).ok_or(SystemError::EINVAL)?;
2556fc066acSJomo         let key = kernel_shm.kern_ipc_perm.key.data().to_i32().unwrap();
2566fc066acSJomo         let mode = kernel_shm.kern_ipc_perm.mode.bits();
2576fc066acSJomo 
2586fc066acSJomo         let shm_perm = PosixIpcPerm::new(key, 0, 0, 0, 0, mode);
2596fc066acSJomo         let shm_segsz = kernel_shm.shm_size;
2606fc066acSJomo         let shm_atime = kernel_shm.shm_atim.total_nanos();
2616fc066acSJomo         let shm_dtime = kernel_shm.shm_dtim.total_nanos();
2626fc066acSJomo         let shm_ctime = kernel_shm.shm_ctim.total_nanos();
2636fc066acSJomo         let shm_cpid = kernel_shm.shm_cprid.data().to_u32().unwrap();
2646fc066acSJomo         let shm_lpid = kernel_shm.shm_lprid.data().to_u32().unwrap();
2656fc066acSJomo         let shm_map_count = kernel_shm.map_count();
2666fc066acSJomo         let shm_id_ds = PosixShmIdDs {
2676fc066acSJomo             shm_perm,
2686fc066acSJomo             shm_segsz,
2696fc066acSJomo             shm_atime,
2706fc066acSJomo             shm_dtime,
2716fc066acSJomo             shm_ctime,
2726fc066acSJomo             shm_cpid,
2736fc066acSJomo             shm_lpid,
2746fc066acSJomo             shm_map_count,
2756fc066acSJomo             _unused1: 0,
2766fc066acSJomo             _unused2: 0,
2776fc066acSJomo         };
2786fc066acSJomo 
2796fc066acSJomo         let mut user_buffer_writer = UserBufferWriter::new(
2806fc066acSJomo             user_buf as *mut u8,
2816fc066acSJomo             core::mem::size_of::<PosixShmIdDs>(),
2826fc066acSJomo             from_user,
2836fc066acSJomo         )?;
2846fc066acSJomo         user_buffer_writer.copy_one_to_user(&shm_id_ds, 0)?;
2856fc066acSJomo 
2866fc066acSJomo         let r: usize = if cmd == ShmCtlCmd::IpcStat {
2876fc066acSJomo             0
2886fc066acSJomo         } else {
2896fc066acSJomo             id.data()
2906fc066acSJomo         };
2916fc066acSJomo 
2926fc066acSJomo         return Ok(r);
2936fc066acSJomo     }
2946fc066acSJomo 
2956fc066acSJomo     pub fn ipc_set(
2966fc066acSJomo         &mut self,
2976fc066acSJomo         id: ShmId,
2986fc066acSJomo         user_buf: *const u8,
2996fc066acSJomo         from_user: bool,
3006fc066acSJomo     ) -> Result<usize, SystemError> {
3016fc066acSJomo         let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
3026fc066acSJomo 
3036fc066acSJomo         let user_buffer_reader =
3046fc066acSJomo             UserBufferReader::new(user_buf, core::mem::size_of::<PosixShmIdDs>(), from_user)?;
3056fc066acSJomo         let mut shm_id_ds = PosixShmIdDs::default();
3066fc066acSJomo         user_buffer_reader.copy_one_from_user(&mut shm_id_ds, 0)?;
3076fc066acSJomo 
3086fc066acSJomo         kernel_shm.copy_from(shm_id_ds);
3096fc066acSJomo 
3106fc066acSJomo         return Ok(0);
3116fc066acSJomo     }
3126fc066acSJomo 
3136fc066acSJomo     pub fn ipc_rmid(&mut self, id: ShmId) -> Result<usize, SystemError> {
3146fc066acSJomo         let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
3156fc066acSJomo         kernel_shm.set_mode(ShmFlags::SHM_DEST, true);
3166fc066acSJomo 
3176fc066acSJomo         let mut cur_phys = PhysPageFrame::new(kernel_shm.shm_start_paddr);
3186fc066acSJomo         let count = PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)).unwrap();
3196fc066acSJomo         let key = kernel_shm.kern_ipc_perm.key;
3206fc066acSJomo         let id = kernel_shm.kern_ipc_perm.id;
3216fc066acSJomo         let map_count = kernel_shm.map_count();
3226fc066acSJomo 
3236fc066acSJomo         let mut page_manager_guard = page_manager_lock_irqsave();
3246fc066acSJomo         if map_count > 0 {
3256fc066acSJomo             // 设置共享内存物理页当映射计数等于0时可被回收
3266fc066acSJomo             for _ in 0..count.data() {
3276fc066acSJomo                 let page = page_manager_guard.get_mut(&cur_phys.phys_address());
3286fc066acSJomo                 page.set_dealloc_when_zero(true);
3296fc066acSJomo 
3306fc066acSJomo                 cur_phys = cur_phys.next();
3316fc066acSJomo             }
3326fc066acSJomo 
3336fc066acSJomo             // 释放key,不让后续进程连接
3346fc066acSJomo             self.free_key(&key);
3356fc066acSJomo         } else {
3366fc066acSJomo             // 释放共享内存物理页
3376fc066acSJomo             for _ in 0..count.data() {
3386fc066acSJomo                 let paddr = cur_phys.phys_address();
3396fc066acSJomo                 unsafe {
3406fc066acSJomo                     LockedFrameAllocator.free(paddr, PageFrameCount::new(1));
3416fc066acSJomo                 }
3426fc066acSJomo                 // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
3436fc066acSJomo                 page_manager_guard.remove_page(&paddr);
3446fc066acSJomo                 cur_phys = cur_phys.next();
3456fc066acSJomo             }
3466fc066acSJomo 
3476fc066acSJomo             // 释放key和id
3486fc066acSJomo             self.free_id(&id);
3496fc066acSJomo             self.free_key(&key)
3506fc066acSJomo         }
3516fc066acSJomo 
3526fc066acSJomo         return Ok(0);
3536fc066acSJomo     }
3546fc066acSJomo 
3556fc066acSJomo     pub fn shm_lock(&mut self, id: ShmId) -> Result<usize, SystemError> {
3566fc066acSJomo         let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
3576fc066acSJomo         kernel_shm.set_mode(ShmFlags::SHM_LOCKED, true);
3586fc066acSJomo 
3596fc066acSJomo         return Ok(0);
3606fc066acSJomo     }
3616fc066acSJomo 
3626fc066acSJomo     pub fn shm_unlock(&mut self, id: ShmId) -> Result<usize, SystemError> {
3636fc066acSJomo         let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
3646fc066acSJomo         kernel_shm.set_mode(ShmFlags::SHM_LOCKED, false);
3656fc066acSJomo 
3666fc066acSJomo         return Ok(0);
3676fc066acSJomo     }
3686fc066acSJomo }
3696fc066acSJomo /// 共享内存信息
3706fc066acSJomo #[derive(Debug)]
3716fc066acSJomo pub struct KernelShm {
3726fc066acSJomo     /// 权限信息
3736fc066acSJomo     kern_ipc_perm: KernIpcPerm,
3746fc066acSJomo     /// 共享内存起始物理地址
3756fc066acSJomo     shm_start_paddr: PhysAddr,
3766fc066acSJomo     /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐)
3776fc066acSJomo     shm_size: usize,
3786fc066acSJomo     /// 最后一次连接的时间
3796fc066acSJomo     shm_atim: PosixTimeSpec,
3806fc066acSJomo     /// 最后一次断开连接的时间
3816fc066acSJomo     shm_dtim: PosixTimeSpec,
3826fc066acSJomo     /// 最后一次更改信息的时间
3836fc066acSJomo     shm_ctim: PosixTimeSpec,
3846fc066acSJomo     /// 创建者进程id
3856fc066acSJomo     shm_cprid: Pid,
3866fc066acSJomo     /// 最后操作者进程id
3876fc066acSJomo     shm_lprid: Pid,
3886fc066acSJomo }
3896fc066acSJomo 
3906fc066acSJomo impl KernelShm {
3916fc066acSJomo     pub fn new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self {
3926fc066acSJomo         let shm_cprid = ProcessManager::current_pid();
3936fc066acSJomo         KernelShm {
3946fc066acSJomo             kern_ipc_perm,
3956fc066acSJomo             shm_start_paddr,
3966fc066acSJomo             shm_size,
3976fc066acSJomo             shm_atim: PosixTimeSpec::new(0, 0),
3986fc066acSJomo             shm_dtim: PosixTimeSpec::new(0, 0),
3996fc066acSJomo             shm_ctim: PosixTimeSpec::now(),
4006fc066acSJomo             shm_cprid,
4016fc066acSJomo             shm_lprid: shm_cprid,
4026fc066acSJomo         }
4036fc066acSJomo     }
4046fc066acSJomo 
4056fc066acSJomo     pub fn start_paddr(&self) -> PhysAddr {
4066fc066acSJomo         self.shm_start_paddr
4076fc066acSJomo     }
4086fc066acSJomo 
4096fc066acSJomo     pub fn size(&self) -> usize {
4106fc066acSJomo         self.shm_size
4116fc066acSJomo     }
4126fc066acSJomo 
4136fc066acSJomo     /// 更新最后连接时间
4146fc066acSJomo     pub fn update_atim(&mut self) {
4156fc066acSJomo         // 更新最后一次连接时间
4166fc066acSJomo         self.shm_atim = PosixTimeSpec::now();
4176fc066acSJomo 
4186fc066acSJomo         // 更新最后操作当前共享内存的进程ID
4196fc066acSJomo         self.shm_lprid = ProcessManager::current_pid();
4206fc066acSJomo     }
4216fc066acSJomo 
4226fc066acSJomo     /// 更新最后断开连接时间
4236fc066acSJomo     pub fn update_dtim(&mut self) {
4246fc066acSJomo         // 更新最后一次断开连接时间
4256fc066acSJomo         self.shm_dtim = PosixTimeSpec::now();
4266fc066acSJomo 
4276fc066acSJomo         // 更新最后操作当前共享内存的进程ID
4286fc066acSJomo         self.shm_lprid = ProcessManager::current_pid();
4296fc066acSJomo     }
4306fc066acSJomo 
4316fc066acSJomo     /// 更新最后一次修改信息的时间
4326fc066acSJomo     pub fn update_ctim(&mut self) {
4336fc066acSJomo         // 更新最后一次修改信息的时间
4346fc066acSJomo         self.shm_ctim = PosixTimeSpec::now();
4356fc066acSJomo     }
4366fc066acSJomo 
4376fc066acSJomo     /// 共享内存段的映射计数(有多少个不同的VMA映射)
4386fc066acSJomo     pub fn map_count(&self) -> usize {
4396fc066acSJomo         let page_manager_guard = page_manager_lock_irqsave();
4406fc066acSJomo         let mut id_set: HashSet<usize> = HashSet::new();
4416fc066acSJomo         let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr);
4426fc066acSJomo         let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap();
4436fc066acSJomo 
4446fc066acSJomo         for _ in 0..page_count.data() {
4456fc066acSJomo             let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
4466fc066acSJomo             id_set.extend(
4476fc066acSJomo                 page.anon_vma()
4486fc066acSJomo                     .iter()
4496fc066acSJomo                     .map(|vma| vma.id())
4506fc066acSJomo                     .collect::<Vec<_>>(),
4516fc066acSJomo             );
4526fc066acSJomo 
4536fc066acSJomo             cur_phys = cur_phys.next();
4546fc066acSJomo         }
4556fc066acSJomo 
4566fc066acSJomo         // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段
4576fc066acSJomo         return id_set.len();
4586fc066acSJomo     }
4596fc066acSJomo 
4606fc066acSJomo     pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) {
4616fc066acSJomo         self.kern_ipc_perm.uid = shm_id_ds.uid() as usize;
4626fc066acSJomo         self.kern_ipc_perm.gid = shm_id_ds.gid() as usize;
4636fc066acSJomo         self.kern_ipc_perm.mode = ShmFlags::from_bits_truncate(shm_id_ds.mode());
4646fc066acSJomo         self.update_ctim();
4656fc066acSJomo     }
4666fc066acSJomo 
4676fc066acSJomo     pub fn set_mode(&mut self, shmflg: ShmFlags, set: bool) {
4686fc066acSJomo         if set {
4696fc066acSJomo             self.kern_ipc_perm.mode.insert(shmflg);
4706fc066acSJomo         } else {
4716fc066acSJomo             self.kern_ipc_perm.mode.remove(shmflg);
4726fc066acSJomo         }
4736fc066acSJomo 
4746fc066acSJomo         self.update_ctim();
4756fc066acSJomo     }
4766fc066acSJomo }
4776fc066acSJomo 
4786fc066acSJomo /// 共享内存权限信息
4796fc066acSJomo #[derive(Debug)]
4806fc066acSJomo pub struct KernIpcPerm {
4816fc066acSJomo     /// 共享内存id
4826fc066acSJomo     id: ShmId,
4836fc066acSJomo     /// 共享内存键值,由创建共享内存用户指定
4846fc066acSJomo     key: ShmKey,
4856fc066acSJomo     /// 共享内存拥有者用户id
4866fc066acSJomo     uid: usize,
4876fc066acSJomo     /// 共享内存拥有者所在组id
4886fc066acSJomo     gid: usize,
4896fc066acSJomo     /// 共享内存创建者用户id
4906fc066acSJomo     _cuid: usize,
4916fc066acSJomo     /// 共享内存创建者所在组id
4926fc066acSJomo     _cgid: usize,
4936fc066acSJomo     /// 共享内存区权限模式
4946fc066acSJomo     mode: ShmFlags,
4956fc066acSJomo     _seq: usize,
4966fc066acSJomo }
4976fc066acSJomo 
4986fc066acSJomo /// 共享内存元信息,符合POSIX标准
4996fc066acSJomo #[repr(C)]
5006fc066acSJomo #[derive(Debug, Clone, Copy)]
5016fc066acSJomo pub struct PosixShmMetaInfo {
5026fc066acSJomo     /// 最大共享内存段的大小(bytes)
5036fc066acSJomo     shmmax: usize,
5046fc066acSJomo     /// 最小共享内存段的大小(bytes)
5056fc066acSJomo     shmmin: usize,
5066fc066acSJomo     /// 最大共享内存标识符数量
5076fc066acSJomo     shmmni: usize,
5086fc066acSJomo     /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
5096fc066acSJomo     shmseg: usize,
5106fc066acSJomo     /// 所有共享内存段总共可以使用的最大内存量(pages)
5116fc066acSJomo     shmall: usize,
5126fc066acSJomo     _unused1: usize,
5136fc066acSJomo     _unused2: usize,
5146fc066acSJomo     _unused3: usize,
5156fc066acSJomo     _unused4: usize,
5166fc066acSJomo }
5176fc066acSJomo 
5186fc066acSJomo impl PosixShmMetaInfo {
5196fc066acSJomo     /// 最小共享内存段的大小(bytes)
5206fc066acSJomo     pub const SHMMIN: usize = 1;
5216fc066acSJomo     /// 最大共享内存标识符数量
5226fc066acSJomo     pub const SHMMNI: usize = 4096;
5236fc066acSJomo     /// 最大共享内存段的大小(bytes)
5246fc066acSJomo     pub const SHMMAX: usize = usize::MAX - (1 << 24);
5256fc066acSJomo     /// 所有共享内存段总共可以使用的最大内存量(pages)
5266fc066acSJomo     pub const SHMALL: usize = usize::MAX - (1 << 24);
5276fc066acSJomo     /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
5286fc066acSJomo     pub const SHMSEG: usize = 4096;
5296fc066acSJomo 
5306fc066acSJomo     pub fn new() -> Self {
5316fc066acSJomo         PosixShmMetaInfo {
5326fc066acSJomo             shmmax: Self::SHMMAX,
5336fc066acSJomo             shmmin: Self::SHMMIN,
5346fc066acSJomo             shmmni: Self::SHMMNI,
5356fc066acSJomo             shmseg: Self::SHMSEG,
5366fc066acSJomo             shmall: Self::SHMALL,
5376fc066acSJomo             _unused1: 0,
5386fc066acSJomo             _unused2: 0,
5396fc066acSJomo             _unused3: 0,
5406fc066acSJomo             _unused4: 0,
5416fc066acSJomo         }
5426fc066acSJomo     }
5436fc066acSJomo }
5446fc066acSJomo 
5456fc066acSJomo /// 共享内存信息,符合POSIX标准
5466fc066acSJomo #[repr(C)]
5476fc066acSJomo #[derive(Clone, Copy)]
5486fc066acSJomo pub struct PosixShmInfo {
5496fc066acSJomo     /// 已使用id数
5506fc066acSJomo     used_ids: i32,
5516fc066acSJomo     /// 共享内存总量(pages)
5526fc066acSJomo     shm_tot: usize,
5536fc066acSJomo     /// 保留在内存中的共享内存大小
5546fc066acSJomo     shm_rss: usize,
5556fc066acSJomo     /// 被置换出的共享内存大小
5566fc066acSJomo     shm_swp: usize,
5576fc066acSJomo     /// 尝试置换次数
5586fc066acSJomo     swap_attempts: usize,
5596fc066acSJomo     /// 成功置换次数
5606fc066acSJomo     swap_successes: usize,
5616fc066acSJomo }
5626fc066acSJomo 
5636fc066acSJomo impl PosixShmInfo {
5646fc066acSJomo     pub fn new(
5656fc066acSJomo         used_ids: i32,
5666fc066acSJomo         shm_tot: usize,
5676fc066acSJomo         shm_rss: usize,
5686fc066acSJomo         shm_swp: usize,
5696fc066acSJomo         swap_attempts: usize,
5706fc066acSJomo         swap_successes: usize,
5716fc066acSJomo     ) -> Self {
5726fc066acSJomo         PosixShmInfo {
5736fc066acSJomo             used_ids,
5746fc066acSJomo             shm_tot,
5756fc066acSJomo             shm_rss,
5766fc066acSJomo             shm_swp,
5776fc066acSJomo             swap_attempts,
5786fc066acSJomo             swap_successes,
5796fc066acSJomo         }
5806fc066acSJomo     }
5816fc066acSJomo }
5826fc066acSJomo 
5836fc066acSJomo /// 共享内存段属性信息,符合POSIX标准
5846fc066acSJomo #[repr(C)]
5856fc066acSJomo #[derive(Debug, Clone, Copy, Default)]
5866fc066acSJomo pub struct PosixShmIdDs {
5876fc066acSJomo     /// 共享内存段权限
5886fc066acSJomo     shm_perm: PosixIpcPerm,
5896fc066acSJomo     /// 共享内存大小(bytes)
5906fc066acSJomo     shm_segsz: usize,
5916fc066acSJomo     /// 最后一次连接的时间
5926fc066acSJomo     shm_atime: i64,
5936fc066acSJomo     /// 最后一次断开连接的时间
5946fc066acSJomo     shm_dtime: i64,
5956fc066acSJomo     /// 最后一次更改信息的时间
5966fc066acSJomo     shm_ctime: i64,
5976fc066acSJomo     /// 创建者进程id
5986fc066acSJomo     shm_cpid: u32,
5996fc066acSJomo     /// 最后操作者进程id
6006fc066acSJomo     shm_lpid: u32,
6016fc066acSJomo     /// 链接数
6026fc066acSJomo     shm_map_count: usize,
6036fc066acSJomo     _unused1: usize,
6046fc066acSJomo     _unused2: usize,
6056fc066acSJomo }
6066fc066acSJomo 
6076fc066acSJomo impl PosixShmIdDs {
6086fc066acSJomo     pub fn uid(&self) -> u32 {
6096fc066acSJomo         self.shm_perm.uid
6106fc066acSJomo     }
6116fc066acSJomo 
6126fc066acSJomo     pub fn gid(&self) -> u32 {
6136fc066acSJomo         self.shm_perm.gid
6146fc066acSJomo     }
6156fc066acSJomo 
6166fc066acSJomo     pub fn mode(&self) -> u32 {
6176fc066acSJomo         self.shm_perm.mode
6186fc066acSJomo     }
6196fc066acSJomo }
6206fc066acSJomo 
6216fc066acSJomo /// 共享内存段权限,符合POSIX标准
6226fc066acSJomo #[repr(C)]
6236fc066acSJomo #[derive(Debug, Clone, Copy, Default)]
6246fc066acSJomo pub struct PosixIpcPerm {
6256fc066acSJomo     /// IPC对象键值
6266fc066acSJomo     key: i32,
6276fc066acSJomo     /// 当前用户id
6286fc066acSJomo     uid: u32,
6296fc066acSJomo     /// 当前用户组id
6306fc066acSJomo     gid: u32,
6316fc066acSJomo     /// 创建者用户id
6326fc066acSJomo     cuid: u32,
6336fc066acSJomo     /// 创建者组id
6346fc066acSJomo     cgid: u32,
6356fc066acSJomo     /// 权限
6366fc066acSJomo     mode: u32,
6376fc066acSJomo     /// 序列号
6386fc066acSJomo     seq: i32,
6396fc066acSJomo     _pad1: i32,
6406fc066acSJomo     _unused1: usize,
6416fc066acSJomo     _unused2: usize,
6426fc066acSJomo }
6436fc066acSJomo 
6446fc066acSJomo impl PosixIpcPerm {
6456fc066acSJomo     pub fn new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self {
6466fc066acSJomo         PosixIpcPerm {
6476fc066acSJomo             key,
6486fc066acSJomo             uid,
6496fc066acSJomo             gid,
6506fc066acSJomo             cuid,
6516fc066acSJomo             cgid,
6526fc066acSJomo             mode,
6536fc066acSJomo             seq: 0,
6546fc066acSJomo             _pad1: 0,
6556fc066acSJomo             _unused1: 0,
6566fc066acSJomo             _unused2: 0,
6576fc066acSJomo         }
6586fc066acSJomo     }
6596fc066acSJomo }
660