123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660 |
- use crate::{
- arch::mm::LockedFrameAllocator,
- filesystem::vfs::syscall::ModeType,
- libs::{
- align::page_align_up,
- spinlock::{SpinLock, SpinLockGuard},
- },
- mm::{
- allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
- page::{page_manager_lock_irqsave, Page},
- PhysAddr,
- },
- process::{Pid, ProcessManager},
- syscall::user_access::{UserBufferReader, UserBufferWriter},
- time::PosixTimeSpec,
- };
- use alloc::{sync::Arc, vec::Vec};
- use core::sync::atomic::{compiler_fence, Ordering};
- use hashbrown::{HashMap, HashSet};
- 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);
- bitflags! {
- pub struct ShmFlags:u32{
- const SHM_RDONLY = 0o10000;
- const SHM_RND = 0o20000;
- const SHM_REMAP = 0o40000;
- const SHM_EXEC = 0o100000;
- const SHM_HUGETLB = 0o4000;
- const IPC_CREAT = 0o1000;
- const IPC_EXCL = 0o2000;
- const SHM_DEST = 0o1000;
- const SHM_LOCKED = 0o2000;
- }
- }
- /// 管理共享内存段信息的操作码
- #[derive(Eq, Clone, Copy)]
- pub enum ShmCtlCmd {
- /// 删除共享内存段
- IpcRmid = 0,
- /// 设置KernIpcPerm选项
- IpcSet = 1,
- /// 获取ShmIdDs
- IpcStat = 2,
- /// 查看ShmMetaData
- IpcInfo = 3,
- /// 不允许共享内存段被置换出物理内存
- ShmLock = 11,
- /// 允许共享内存段被置换出物理内存
- ShmUnlock = 12,
- /// 查看ShmMetaData
- ShmStat = 13,
- /// 查看ShmInfo
- ShmInfo = 14,
- /// 查看ShmMetaData
- ShmtStatAny = 15,
- Default,
- }
- impl From<usize> for ShmCtlCmd {
- fn from(cmd: usize) -> ShmCtlCmd {
- match cmd {
- 0 => Self::IpcRmid,
- 1 => Self::IpcSet,
- 2 => Self::IpcStat,
- 3 => Self::IpcInfo,
- 11 => Self::ShmLock,
- 12 => Self::ShmUnlock,
- 13 => Self::ShmStat,
- 14 => Self::ShmInfo,
- 15 => Self::ShmtStatAny,
- _ => Self::Default,
- }
- }
- }
- impl PartialEq for ShmCtlCmd {
- fn eq(&self, other: &ShmCtlCmd) -> bool {
- *self as usize == *other as usize
- }
- }
- /// 共享内存管理器
- #[derive(Debug)]
- pub struct ShmManager {
- /// ShmId分配器
- id_allocator: IdAllocator,
- /// ShmId映射共享内存信息表
- id2shm: HashMap<ShmId, KernelShm>,
- /// ShmKey映射ShmId表
- key2id: HashMap<ShmKey, ShmId>,
- }
- impl ShmManager {
- pub fn new() -> Self {
- ShmManager {
- id_allocator: IdAllocator::new(0, usize::MAX - 1),
- id2shm: HashMap::new(),
- key2id: HashMap::new(),
- }
- }
- /// # 添加共享内存段
- ///
- /// ## 参数
- ///
- /// - `key`: 共享内存键值
- /// - `size`: 共享内存大小
- /// - `shmflg`: 共享内存标志
- ///
- /// ## 返回值
- ///
- /// 成功:共享内存id
- /// 失败:对应错误码
- pub fn add(
- &mut self,
- key: ShmKey,
- size: usize,
- shmflg: ShmFlags,
- ) -> Result<usize, SystemError> {
- // 判断共享内存大小是否过小或溢出
- if !(PosixShmMetaInfo::SHMMIN..=PosixShmMetaInfo::SHMMAX).contains(&size) {
- return Err(SystemError::EINVAL);
- }
- let id = self.id_allocator.alloc().expect("No more id to allocate.");
- let shm_id = ShmId::new(id);
- // 分配共享内存页面
- let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap();
- let phys_page =
- unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?;
- // 创建共享内存page,并添加到PAGE_MANAGER中
- let mut page_manager_guard = page_manager_lock_irqsave();
- let mut cur_phys = PhysPageFrame::new(phys_page.0);
- for _ in 0..page_count.data() {
- let page = Arc::new(Page::new(true, cur_phys));
- page.write().set_shm_id(shm_id);
- let paddr = cur_phys.phys_address();
- page_manager_guard.insert(paddr, &page);
- cur_phys = cur_phys.next();
- }
- // 创建共享内存信息结构体
- let paddr = phys_page.0;
- let kern_ipc_perm = KernIpcPerm {
- id: shm_id,
- key,
- uid: 0,
- gid: 0,
- _cuid: 0,
- _cgid: 0,
- mode: shmflg & ShmFlags::from_bits_truncate(ModeType::S_IRWXUGO.bits()),
- _seq: 0,
- };
- let shm_kernel = KernelShm::new(kern_ipc_perm, paddr, size);
- // 将key、id及其对应KernelShm添加到表中
- self.id2shm.insert(shm_id, shm_kernel);
- self.key2id.insert(key, shm_id);
- return Ok(shm_id.data());
- }
- pub fn contains_key(&self, key: &ShmKey) -> Option<&ShmId> {
- self.key2id.get(key)
- }
- pub fn get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm> {
- self.id2shm.get_mut(id)
- }
- pub fn free_key(&mut self, key: &ShmKey) {
- self.key2id.remove(key);
- }
- pub fn free_id(&mut self, id: &ShmId) {
- self.id2shm.remove(id);
- self.id_allocator.free(id.0);
- }
- pub fn ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
- let mut user_buffer_writer = UserBufferWriter::new(
- user_buf as *mut u8,
- core::mem::size_of::<PosixShmMetaInfo>(),
- from_user,
- )?;
- let shm_meta_info = PosixShmMetaInfo::new();
- user_buffer_writer.copy_one_to_user(&shm_meta_info, 0)?;
- return Ok(0);
- }
- pub fn shm_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
- // 已使用id数量
- let used_ids = self.id2shm.len().to_i32().unwrap();
- // 共享内存总和
- let shm_tot = self.id2shm.iter().fold(0, |acc, (_, kernel_shm)| {
- acc + PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size))
- .unwrap()
- .data()
- });
- let shm_info = PosixShmInfo::new(used_ids, shm_tot, 0, 0, 0, 0);
- let mut user_buffer_writer = UserBufferWriter::new(
- user_buf as *mut u8,
- core::mem::size_of::<PosixShmInfo>(),
- from_user,
- )?;
- user_buffer_writer.copy_one_to_user(&shm_info, 0)?;
- return Ok(0);
- }
- pub fn shm_stat(
- &self,
- id: ShmId,
- cmd: ShmCtlCmd,
- user_buf: *const u8,
- from_user: bool,
- ) -> Result<usize, SystemError> {
- let kernel_shm = self.id2shm.get(&id).ok_or(SystemError::EINVAL)?;
- let key = kernel_shm.kern_ipc_perm.key.data().to_i32().unwrap();
- let mode = kernel_shm.kern_ipc_perm.mode.bits();
- let shm_perm = PosixIpcPerm::new(key, 0, 0, 0, 0, mode);
- let shm_segsz = kernel_shm.shm_size;
- let shm_atime = kernel_shm.shm_atim.total_nanos();
- let shm_dtime = kernel_shm.shm_dtim.total_nanos();
- let shm_ctime = kernel_shm.shm_ctim.total_nanos();
- let shm_cpid = kernel_shm.shm_cprid.data().to_u32().unwrap();
- let shm_lpid = kernel_shm.shm_lprid.data().to_u32().unwrap();
- let shm_map_count = kernel_shm.map_count();
- let shm_id_ds = PosixShmIdDs {
- shm_perm,
- shm_segsz,
- shm_atime,
- shm_dtime,
- shm_ctime,
- shm_cpid,
- shm_lpid,
- shm_map_count,
- _unused1: 0,
- _unused2: 0,
- };
- let mut user_buffer_writer = UserBufferWriter::new(
- user_buf as *mut u8,
- core::mem::size_of::<PosixShmIdDs>(),
- from_user,
- )?;
- user_buffer_writer.copy_one_to_user(&shm_id_ds, 0)?;
- let r: usize = if cmd == ShmCtlCmd::IpcStat {
- 0
- } else {
- id.data()
- };
- return Ok(r);
- }
- pub fn ipc_set(
- &mut self,
- id: ShmId,
- user_buf: *const u8,
- from_user: bool,
- ) -> Result<usize, SystemError> {
- let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
- let user_buffer_reader =
- UserBufferReader::new(user_buf, core::mem::size_of::<PosixShmIdDs>(), from_user)?;
- let mut shm_id_ds = PosixShmIdDs::default();
- user_buffer_reader.copy_one_from_user(&mut shm_id_ds, 0)?;
- kernel_shm.copy_from(shm_id_ds);
- return Ok(0);
- }
- pub fn ipc_rmid(&mut self, id: ShmId) -> Result<usize, SystemError> {
- let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
- kernel_shm.set_mode(ShmFlags::SHM_DEST, true);
- let mut cur_phys = PhysPageFrame::new(kernel_shm.shm_start_paddr);
- let count = PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)).unwrap();
- let key = kernel_shm.kern_ipc_perm.key;
- let id = kernel_shm.kern_ipc_perm.id;
- let map_count = kernel_shm.map_count();
- let mut page_manager_guard = page_manager_lock_irqsave();
- if map_count > 0 {
- // 设置共享内存物理页当映射计数等于0时可被回收
- for _ in 0..count.data() {
- let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
- page.write().set_dealloc_when_zero(true);
- cur_phys = cur_phys.next();
- }
- // 释放key,不让后续进程连接
- self.free_key(&key);
- } else {
- // 释放共享内存物理页
- for _ in 0..count.data() {
- let paddr = cur_phys.phys_address();
- unsafe {
- LockedFrameAllocator.free(paddr, PageFrameCount::new(1));
- }
- // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
- page_manager_guard.remove_page(&paddr);
- cur_phys = cur_phys.next();
- }
- // 释放key和id
- self.free_id(&id);
- self.free_key(&key)
- }
- return Ok(0);
- }
- pub fn shm_lock(&mut self, id: ShmId) -> Result<usize, SystemError> {
- let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
- kernel_shm.set_mode(ShmFlags::SHM_LOCKED, true);
- return Ok(0);
- }
- pub fn shm_unlock(&mut self, id: ShmId) -> Result<usize, SystemError> {
- let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
- kernel_shm.set_mode(ShmFlags::SHM_LOCKED, false);
- return Ok(0);
- }
- }
- /// 共享内存信息
- #[derive(Debug)]
- pub struct KernelShm {
- /// 权限信息
- kern_ipc_perm: KernIpcPerm,
- /// 共享内存起始物理地址
- shm_start_paddr: PhysAddr,
- /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐)
- shm_size: usize,
- /// 最后一次连接的时间
- shm_atim: PosixTimeSpec,
- /// 最后一次断开连接的时间
- shm_dtim: PosixTimeSpec,
- /// 最后一次更改信息的时间
- shm_ctim: PosixTimeSpec,
- /// 创建者进程id
- shm_cprid: Pid,
- /// 最后操作者进程id
- shm_lprid: Pid,
- }
- impl KernelShm {
- pub fn new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self {
- let shm_cprid = ProcessManager::current_pid();
- KernelShm {
- kern_ipc_perm,
- shm_start_paddr,
- shm_size,
- shm_atim: PosixTimeSpec::new(0, 0),
- shm_dtim: PosixTimeSpec::new(0, 0),
- shm_ctim: PosixTimeSpec::now(),
- shm_cprid,
- shm_lprid: shm_cprid,
- }
- }
- pub fn start_paddr(&self) -> PhysAddr {
- self.shm_start_paddr
- }
- pub fn size(&self) -> usize {
- self.shm_size
- }
- /// 更新最后连接时间
- pub fn update_atim(&mut self) {
- // 更新最后一次连接时间
- self.shm_atim = PosixTimeSpec::now();
- // 更新最后操作当前共享内存的进程ID
- self.shm_lprid = ProcessManager::current_pid();
- }
- /// 更新最后断开连接时间
- pub fn update_dtim(&mut self) {
- // 更新最后一次断开连接时间
- self.shm_dtim = PosixTimeSpec::now();
- // 更新最后操作当前共享内存的进程ID
- self.shm_lprid = ProcessManager::current_pid();
- }
- /// 更新最后一次修改信息的时间
- pub fn update_ctim(&mut self) {
- // 更新最后一次修改信息的时间
- self.shm_ctim = PosixTimeSpec::now();
- }
- /// 共享内存段的映射计数(有多少个不同的VMA映射)
- pub fn map_count(&self) -> usize {
- let page_manager_guard = page_manager_lock_irqsave();
- let mut id_set: HashSet<usize> = HashSet::new();
- let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr);
- let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap();
- for _ in 0..page_count.data() {
- let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
- id_set.extend(
- page.read()
- .anon_vma()
- .iter()
- .map(|vma| vma.id())
- .collect::<Vec<_>>(),
- );
- cur_phys = cur_phys.next();
- }
- // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段
- return id_set.len();
- }
- pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) {
- self.kern_ipc_perm.uid = shm_id_ds.uid() as usize;
- self.kern_ipc_perm.gid = shm_id_ds.gid() as usize;
- self.kern_ipc_perm.mode = ShmFlags::from_bits_truncate(shm_id_ds.mode());
- self.update_ctim();
- }
- pub fn set_mode(&mut self, shmflg: ShmFlags, set: bool) {
- if set {
- self.kern_ipc_perm.mode.insert(shmflg);
- } else {
- self.kern_ipc_perm.mode.remove(shmflg);
- }
- self.update_ctim();
- }
- }
- /// 共享内存权限信息
- #[derive(Debug)]
- pub struct KernIpcPerm {
- /// 共享内存id
- id: ShmId,
- /// 共享内存键值,由创建共享内存用户指定
- key: ShmKey,
- /// 共享内存拥有者用户id
- uid: usize,
- /// 共享内存拥有者所在组id
- gid: usize,
- /// 共享内存创建者用户id
- _cuid: usize,
- /// 共享内存创建者所在组id
- _cgid: usize,
- /// 共享内存区权限模式
- mode: ShmFlags,
- _seq: usize,
- }
- /// 共享内存元信息,符合POSIX标准
- #[repr(C)]
- #[derive(Debug, Clone, Copy)]
- pub struct PosixShmMetaInfo {
- /// 最大共享内存段的大小(bytes)
- shmmax: usize,
- /// 最小共享内存段的大小(bytes)
- shmmin: usize,
- /// 最大共享内存标识符数量
- shmmni: usize,
- /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
- shmseg: usize,
- /// 所有共享内存段总共可以使用的最大内存量(pages)
- shmall: usize,
- _unused1: usize,
- _unused2: usize,
- _unused3: usize,
- _unused4: usize,
- }
- impl PosixShmMetaInfo {
- /// 最小共享内存段的大小(bytes)
- pub const SHMMIN: usize = 1;
- /// 最大共享内存标识符数量
- pub const SHMMNI: usize = 4096;
- /// 最大共享内存段的大小(bytes)
- pub const SHMMAX: usize = usize::MAX - (1 << 24);
- /// 所有共享内存段总共可以使用的最大内存量(pages)
- pub const SHMALL: usize = usize::MAX - (1 << 24);
- /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
- pub const SHMSEG: usize = 4096;
- pub fn new() -> Self {
- PosixShmMetaInfo {
- shmmax: Self::SHMMAX,
- shmmin: Self::SHMMIN,
- shmmni: Self::SHMMNI,
- shmseg: Self::SHMSEG,
- shmall: Self::SHMALL,
- _unused1: 0,
- _unused2: 0,
- _unused3: 0,
- _unused4: 0,
- }
- }
- }
- /// 共享内存信息,符合POSIX标准
- #[repr(C)]
- #[derive(Clone, Copy)]
- pub struct PosixShmInfo {
- /// 已使用id数
- used_ids: i32,
- /// 共享内存总量(pages)
- shm_tot: usize,
- /// 保留在内存中的共享内存大小
- shm_rss: usize,
- /// 被置换出的共享内存大小
- shm_swp: usize,
- /// 尝试置换次数
- swap_attempts: usize,
- /// 成功置换次数
- swap_successes: usize,
- }
- impl PosixShmInfo {
- pub fn new(
- used_ids: i32,
- shm_tot: usize,
- shm_rss: usize,
- shm_swp: usize,
- swap_attempts: usize,
- swap_successes: usize,
- ) -> Self {
- PosixShmInfo {
- used_ids,
- shm_tot,
- shm_rss,
- shm_swp,
- swap_attempts,
- swap_successes,
- }
- }
- }
- /// 共享内存段属性信息,符合POSIX标准
- #[repr(C)]
- #[derive(Debug, Clone, Copy, Default)]
- pub struct PosixShmIdDs {
- /// 共享内存段权限
- shm_perm: PosixIpcPerm,
- /// 共享内存大小(bytes)
- shm_segsz: usize,
- /// 最后一次连接的时间
- shm_atime: i64,
- /// 最后一次断开连接的时间
- shm_dtime: i64,
- /// 最后一次更改信息的时间
- shm_ctime: i64,
- /// 创建者进程id
- shm_cpid: u32,
- /// 最后操作者进程id
- shm_lpid: u32,
- /// 链接数
- shm_map_count: usize,
- _unused1: usize,
- _unused2: usize,
- }
- impl PosixShmIdDs {
- pub fn uid(&self) -> u32 {
- self.shm_perm.uid
- }
- pub fn gid(&self) -> u32 {
- self.shm_perm.gid
- }
- pub fn mode(&self) -> u32 {
- self.shm_perm.mode
- }
- }
- /// 共享内存段权限,符合POSIX标准
- #[repr(C)]
- #[derive(Debug, Clone, Copy, Default)]
- pub struct PosixIpcPerm {
- /// IPC对象键值
- key: i32,
- /// 当前用户id
- uid: u32,
- /// 当前用户组id
- gid: u32,
- /// 创建者用户id
- cuid: u32,
- /// 创建者组id
- cgid: u32,
- /// 权限
- mode: u32,
- /// 序列号
- seq: i32,
- _pad1: i32,
- _unused1: usize,
- _unused2: usize,
- }
- impl PosixIpcPerm {
- pub fn new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self {
- PosixIpcPerm {
- key,
- uid,
- gid,
- cuid,
- cgid,
- mode,
- seq: 0,
- _pad1: 0,
- _unused1: 0,
- _unused2: 0,
- }
- }
- }
|