1 use core::{ 2 ffi::{c_int, c_void}, 3 sync::atomic::compiler_fence, 4 }; 5 6 use log::{error, warn}; 7 use system_error::SystemError; 8 9 use crate::{ 10 arch::{ 11 ipc::signal::{SigCode, SigFlags, SigSet, Signal}, 12 MMArch, 13 }, 14 filesystem::vfs::{ 15 file::{File, FileMode}, 16 FilePrivateData, 17 }, 18 ipc::shm::{shm_manager_lock, IPC_PRIVATE}, 19 libs::align::page_align_up, 20 libs::spinlock::SpinLock, 21 mm::{ 22 allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame}, 23 page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll}, 24 syscall::ProtFlags, 25 ucontext::{AddressSpace, VMA}, 26 VirtAddr, VmFlags, 27 }, 28 process::{Pid, ProcessManager}, 29 syscall::{ 30 user_access::{UserBufferReader, UserBufferWriter}, 31 Syscall, 32 }, 33 }; 34 35 use super::{ 36 pipe::{LockedPipeInode, PipeFsPrivateData}, 37 shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, 38 signal_types::{ 39 SaHandlerType, SigInfo, SigType, Sigaction, SigactionType, UserSigaction, USER_SIG_DFL, 40 USER_SIG_ERR, USER_SIG_IGN, 41 }, 42 }; 43 44 impl Syscall { 45 /// # 创建带参数的匿名管道 46 /// 47 /// ## 参数 48 /// 49 /// - `fd`: 用于返回文件描述符的数组 50 /// - `flags`:设置管道的参数 pipe2(fd: *mut i32, flags: FileMode) -> Result<usize, SystemError>51 pub fn pipe2(fd: *mut i32, flags: FileMode) -> Result<usize, SystemError> { 52 if !flags 53 .difference(FileMode::O_CLOEXEC | FileMode::O_NONBLOCK | FileMode::O_DIRECT) 54 .is_empty() 55 { 56 return Err(SystemError::EINVAL); 57 } 58 59 let mut user_buffer = UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?; 60 let fd = user_buffer.buffer::<i32>(0)?; 61 let pipe_ptr = LockedPipeInode::new(); 62 63 let mut read_file = File::new( 64 pipe_ptr.clone(), 65 FileMode::O_RDONLY | (flags & FileMode::O_NONBLOCK), 66 )?; 67 read_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( 68 FileMode::O_RDONLY, 69 ))); 70 71 let mut write_file = File::new( 72 pipe_ptr.clone(), 73 FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), 74 )?; 75 write_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( 76 FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), 77 ))); 78 79 if flags.contains(FileMode::O_CLOEXEC) { 80 read_file.set_close_on_exec(true); 81 write_file.set_close_on_exec(true); 82 } 83 let fd_table_ptr = ProcessManager::current_pcb().fd_table(); 84 let mut fd_table_guard = fd_table_ptr.write(); 85 let read_fd = fd_table_guard.alloc_fd(read_file, None)?; 86 let write_fd = fd_table_guard.alloc_fd(write_file, None)?; 87 88 drop(fd_table_guard); 89 90 fd[0] = read_fd; 91 fd[1] = write_fd; 92 Ok(0) 93 } 94 kill(pid: Pid, sig: c_int) -> Result<usize, SystemError>95 pub fn kill(pid: Pid, sig: c_int) -> Result<usize, SystemError> { 96 let sig = Signal::from(sig); 97 if sig == Signal::INVALID { 98 // 传入的signal数值不合法 99 warn!("Not a valid signal number"); 100 return Err(SystemError::EINVAL); 101 } 102 103 // 初始化signal info 104 let mut info = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(pid)); 105 106 compiler_fence(core::sync::atomic::Ordering::SeqCst); 107 108 let retval = sig 109 .send_signal_info(Some(&mut info), pid) 110 .map(|x| x as usize); 111 112 compiler_fence(core::sync::atomic::Ordering::SeqCst); 113 114 return retval; 115 } 116 117 /// 通用信号注册函数 118 /// 119 /// ## 参数 120 /// 121 /// - `sig` 信号的值 122 /// - `act` 用户空间传入的 Sigaction 指针 123 /// - `old_act` 用户空间传入的用来保存旧 Sigaction 的指针 124 /// - `from_user` 用来标识这个函数调用是否来自用户空间 125 /// 126 /// @return int 错误码 127 #[no_mangle] sigaction( sig: c_int, new_act: usize, old_act: usize, from_user: bool, ) -> Result<usize, SystemError>128 pub fn sigaction( 129 sig: c_int, 130 new_act: usize, 131 old_act: usize, 132 from_user: bool, 133 ) -> Result<usize, SystemError> { 134 // 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样 135 let act: *mut UserSigaction = new_act as *mut UserSigaction; 136 let old_act = old_act as *mut UserSigaction; 137 let mut new_ka: Sigaction = Default::default(); 138 let mut old_sigaction: Sigaction = Default::default(); 139 // 如果传入的,新的sigaction不为空 140 if !act.is_null() { 141 // 如果参数的范围不在用户空间,则返回错误 142 let r = UserBufferWriter::new(act, core::mem::size_of::<Sigaction>(), from_user); 143 if r.is_err() { 144 return Err(SystemError::EFAULT); 145 } 146 let mask: SigSet = unsafe { (*act).mask }; 147 let input_sighandler = unsafe { (*act).handler as u64 }; 148 match input_sighandler { 149 USER_SIG_DFL => { 150 new_ka = Sigaction::DEFAULT_SIGACTION; 151 *new_ka.flags_mut() = unsafe { (*act).flags }; 152 new_ka.set_restorer(None); 153 } 154 155 USER_SIG_IGN => { 156 new_ka = Sigaction::DEFAULT_SIGACTION_IGNORE; 157 *new_ka.flags_mut() = unsafe { (*act).flags }; 158 159 new_ka.set_restorer(None); 160 } 161 _ => { 162 // 从用户空间获得sigaction结构体 163 // TODO mask是default还是用户空间传入 164 new_ka = Sigaction::new( 165 SigactionType::SaHandler(SaHandlerType::Customized(unsafe { 166 VirtAddr::new((*act).handler as usize) 167 })), 168 unsafe { (*act).flags }, 169 SigSet::default(), 170 unsafe { Some(VirtAddr::new((*act).restorer as usize)) }, 171 ); 172 } 173 } 174 175 // TODO 如果为空,赋默认值? 176 // debug!("new_ka={:?}", new_ka); 177 // 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer) 178 if new_ka.restorer().is_some() { 179 new_ka.flags_mut().insert(SigFlags::SA_RESTORER); 180 } else if new_ka.action().is_customized() { 181 error!( 182 "pid:{:?}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.", 183 ProcessManager::current_pcb().pid(), 184 sig 185 ); 186 return Err(SystemError::EINVAL); 187 } 188 *new_ka.mask_mut() = mask; 189 } 190 191 let sig = Signal::from(sig); 192 // 如果给出的信号值不合法 193 if sig == Signal::INVALID { 194 return Err(SystemError::EINVAL); 195 } 196 197 let retval = super::signal::do_sigaction( 198 sig, 199 if act.is_null() { 200 None 201 } else { 202 Some(&mut new_ka) 203 }, 204 if old_act.is_null() { 205 None 206 } else { 207 Some(&mut old_sigaction) 208 }, 209 ); 210 211 // 212 if (retval == Ok(())) && (!old_act.is_null()) { 213 let r = 214 UserBufferWriter::new(old_act, core::mem::size_of::<UserSigaction>(), from_user); 215 if r.is_err() { 216 return Err(SystemError::EFAULT); 217 } 218 219 let sigaction_handler = match old_sigaction.action() { 220 SigactionType::SaHandler(handler) => { 221 if let SaHandlerType::Customized(hand) = handler { 222 hand 223 } else if handler.is_sig_ignore() { 224 VirtAddr::new(USER_SIG_IGN as usize) 225 } else if handler.is_sig_error() { 226 VirtAddr::new(USER_SIG_ERR as usize) 227 } else { 228 VirtAddr::new(USER_SIG_DFL as usize) 229 } 230 } 231 SigactionType::SaSigaction(_) => { 232 error!("unsupported type: SaSigaction"); 233 VirtAddr::new(USER_SIG_DFL as usize) 234 } 235 }; 236 237 unsafe { 238 (*old_act).handler = sigaction_handler.data() as *mut c_void; 239 (*old_act).flags = old_sigaction.flags(); 240 (*old_act).mask = old_sigaction.mask(); 241 if old_sigaction.restorer().is_some() { 242 (*old_act).restorer = old_sigaction.restorer().unwrap().data() as *mut c_void; 243 } 244 } 245 } 246 return retval.map(|_| 0); 247 } 248 249 /// # SYS_SHMGET系统调用函数,用于获取共享内存 250 /// 251 /// ## 参数 252 /// 253 /// - `key`: 共享内存键值 254 /// - `size`: 共享内存大小(bytes) 255 /// - `shmflg`: 共享内存标志 256 /// 257 /// ## 返回值 258 /// 259 /// 成功:共享内存id 260 /// 失败:错误码 shmget(key: ShmKey, size: usize, shmflg: ShmFlags) -> Result<usize, SystemError>261 pub fn shmget(key: ShmKey, size: usize, shmflg: ShmFlags) -> Result<usize, SystemError> { 262 // 暂不支持巨页 263 if shmflg.contains(ShmFlags::SHM_HUGETLB) { 264 error!("shmget: not support huge page"); 265 return Err(SystemError::ENOSYS); 266 } 267 268 let mut shm_manager_guard = shm_manager_lock(); 269 match key { 270 // 创建共享内存段 271 IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg), 272 _ => { 273 // 查找key对应的共享内存段是否存在 274 let id = shm_manager_guard.contains_key(&key); 275 if let Some(id) = id { 276 // 不能重复创建 277 if shmflg.contains(ShmFlags::IPC_CREAT | ShmFlags::IPC_EXCL) { 278 return Err(SystemError::EEXIST); 279 } 280 281 // key值存在,说明有对应共享内存,返回该共享内存id 282 return Ok(id.data()); 283 } else { 284 // key不存在且shm_flags不包含IPC_CREAT创建IPC对象标志,则返回错误码 285 if !shmflg.contains(ShmFlags::IPC_CREAT) { 286 return Err(SystemError::ENOENT); 287 } 288 289 // 存在创建IPC对象标志 290 return shm_manager_guard.add(key, size, shmflg); 291 } 292 } 293 } 294 } 295 296 /// # SYS_SHMAT系统调用函数,用于连接共享内存段 297 /// 298 /// ## 参数 299 /// 300 /// - `id`: 共享内存id 301 /// - `vaddr`: 连接共享内存的进程虚拟内存区域起始地址 302 /// - `shmflg`: 共享内存标志 303 /// 304 /// ## 返回值 305 /// 306 /// 成功:映射到共享内存的虚拟内存区域起始地址 307 /// 失败:错误码 shmat(id: ShmId, vaddr: VirtAddr, shmflg: ShmFlags) -> Result<usize, SystemError>308 pub fn shmat(id: ShmId, vaddr: VirtAddr, shmflg: ShmFlags) -> Result<usize, SystemError> { 309 let mut shm_manager_guard = shm_manager_lock(); 310 let current_address_space = AddressSpace::current()?; 311 let mut address_write_guard = current_address_space.write(); 312 313 let kernel_shm = shm_manager_guard.get_mut(&id).ok_or(SystemError::EINVAL)?; 314 let size = page_align_up(kernel_shm.size()); 315 let mut phys = PhysPageFrame::new(kernel_shm.start_paddr()); 316 let count = PageFrameCount::from_bytes(size).unwrap(); 317 let r = match vaddr.data() { 318 // 找到空闲区域并映射到共享内存 319 0 => { 320 // 找到空闲区域 321 let region = address_write_guard 322 .mappings 323 .find_free(vaddr, size) 324 .ok_or(SystemError::EINVAL)?; 325 let vm_flags = VmFlags::from(shmflg); 326 let destination = VirtPageFrame::new(region.start()); 327 let page_flags: EntryFlags<MMArch> = 328 EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true); 329 let flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 330 331 // 将共享内存映射到对应虚拟区域 332 let vma = VMA::physmap( 333 phys, 334 destination, 335 count, 336 vm_flags, 337 page_flags, 338 &mut address_write_guard.user_mapper.utable, 339 flusher, 340 )?; 341 342 // 将VMA加入到当前进程的VMA列表中 343 address_write_guard.mappings.insert_vma(vma); 344 345 region.start().data() 346 } 347 // 指定虚拟地址 348 _ => { 349 // 获取对应vma 350 let vma = address_write_guard 351 .mappings 352 .contains(vaddr) 353 .ok_or(SystemError::EINVAL)?; 354 if vma.lock_irqsave().region().start() != vaddr { 355 return Err(SystemError::EINVAL); 356 } 357 358 // 验证用户虚拟内存区域是否有效 359 let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?; 360 361 // 必须在取消映射前获取到EntryFlags 362 let page_flags = address_write_guard 363 .user_mapper 364 .utable 365 .translate(vaddr) 366 .ok_or(SystemError::EINVAL)? 367 .1; 368 369 // 取消原映射 370 let flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 371 vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); 372 373 // 将该虚拟内存区域映射到共享内存区域 374 let mut page_manager_guard = page_manager_lock_irqsave(); 375 let mut virt = VirtPageFrame::new(vaddr); 376 for _ in 0..count.data() { 377 let r = unsafe { 378 address_write_guard.user_mapper.utable.map_phys( 379 virt.virt_address(), 380 phys.phys_address(), 381 page_flags, 382 ) 383 } 384 .expect("Failed to map zero, may be OOM error"); 385 r.flush(); 386 387 // 将vma加入到对应Page的anon_vma 388 page_manager_guard 389 .get_unwrap(&phys.phys_address()) 390 .write_irqsave() 391 .insert_vma(vma.clone()); 392 393 phys = phys.next(); 394 virt = virt.next(); 395 } 396 397 // 更新vma的映射状态 398 vma.lock_irqsave().set_mapped(true); 399 400 vaddr.data() 401 } 402 }; 403 404 // 更新最后一次连接时间 405 kernel_shm.update_atim(); 406 407 Ok(r) 408 } 409 410 /// # SYS_SHMDT系统调用函数,用于取消对共享内存的连接 411 /// 412 /// ## 参数 413 /// 414 /// - `vaddr`: 需要取消映射的虚拟内存区域起始地址 415 /// 416 /// ## 返回值 417 /// 418 /// 成功:0 419 /// 失败:错误码 shmdt(vaddr: VirtAddr) -> Result<usize, SystemError>420 pub fn shmdt(vaddr: VirtAddr) -> Result<usize, SystemError> { 421 let current_address_space = AddressSpace::current()?; 422 let mut address_write_guard = current_address_space.write(); 423 424 // 获取vma 425 let vma = address_write_guard 426 .mappings 427 .contains(vaddr) 428 .ok_or(SystemError::EINVAL)?; 429 430 // 判断vaddr是否为起始地址 431 if vma.lock_irqsave().region().start() != vaddr { 432 return Err(SystemError::EINVAL); 433 } 434 435 // 获取映射的物理地址 436 let paddr = address_write_guard 437 .user_mapper 438 .utable 439 .translate(vaddr) 440 .ok_or(SystemError::EINVAL)? 441 .0; 442 443 // 如果物理页的shm_id为None,代表不是共享页 444 let mut page_manager_guard = page_manager_lock_irqsave(); 445 let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?; 446 let shm_id = page.read_irqsave().shm_id().ok_or(SystemError::EINVAL)?; 447 drop(page_manager_guard); 448 449 // 获取对应共享页管理信息 450 let mut shm_manager_guard = shm_manager_lock(); 451 let kernel_shm = shm_manager_guard 452 .get_mut(&shm_id) 453 .ok_or(SystemError::EINVAL)?; 454 // 更新最后一次断开连接时间 455 kernel_shm.update_dtim(); 456 drop(shm_manager_guard); 457 458 // 取消映射 459 let flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 460 vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); 461 462 return Ok(0); 463 } 464 465 /// # SYS_SHMCTL系统调用函数,用于管理共享内存段 466 /// 467 /// ## 参数 468 /// 469 /// - `id`: 共享内存id 470 /// - `cmd`: 操作码 471 /// - `user_buf`: 用户缓冲区 472 /// - `from_user`: buf_vaddr是否来自用户地址空间 473 /// 474 /// ## 返回值 475 /// 476 /// 成功:0 477 /// 失败:错误码 shmctl( id: ShmId, cmd: ShmCtlCmd, user_buf: *const u8, from_user: bool, ) -> Result<usize, SystemError>478 pub fn shmctl( 479 id: ShmId, 480 cmd: ShmCtlCmd, 481 user_buf: *const u8, 482 from_user: bool, 483 ) -> Result<usize, SystemError> { 484 let mut shm_manager_guard = shm_manager_lock(); 485 486 match cmd { 487 // 查看共享内存元信息 488 ShmCtlCmd::IpcInfo => shm_manager_guard.ipc_info(user_buf, from_user), 489 // 查看共享内存使用信息 490 ShmCtlCmd::ShmInfo => shm_manager_guard.shm_info(user_buf, from_user), 491 // 查看id对应的共享内存信息 492 ShmCtlCmd::ShmStat | ShmCtlCmd::ShmtStatAny | ShmCtlCmd::IpcStat => { 493 shm_manager_guard.shm_stat(id, cmd, user_buf, from_user) 494 } 495 // 设置KernIpcPerm 496 ShmCtlCmd::IpcSet => shm_manager_guard.ipc_set(id, user_buf, from_user), 497 // 将共享内存段设置为可回收状态 498 ShmCtlCmd::IpcRmid => shm_manager_guard.ipc_rmid(id), 499 // 锁住共享内存段,不允许内存置换 500 ShmCtlCmd::ShmLock => shm_manager_guard.shm_lock(id), 501 // 解锁共享内存段,允许内存置换 502 ShmCtlCmd::ShmUnlock => shm_manager_guard.shm_unlock(id), 503 // 无效操作码 504 ShmCtlCmd::Default => Err(SystemError::EINVAL), 505 } 506 } 507 } 508