1 use core::{ 2 ffi::{c_int, c_void}, 3 sync::atomic::compiler_fence, 4 }; 5 6 use system_error::SystemError; 7 8 use crate::{ 9 arch::{ 10 ipc::signal::{SigCode, SigFlags, SigSet, Signal}, 11 MMArch, 12 }, 13 filesystem::vfs::{ 14 file::{File, FileMode}, 15 FilePrivateData, 16 }, 17 ipc::shm::{shm_manager_lock, IPC_PRIVATE}, 18 kerror, kwarn, 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, PageFlags, 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`:设置管道的参数 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 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 kwarn!("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] 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 // kdebug!("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 kerror!( 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 kerror!("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 /// 失败:错误码 261 pub fn shmget(key: ShmKey, size: usize, shmflg: ShmFlags) -> Result<usize, SystemError> { 262 // 暂不支持巨页 263 if shmflg.contains(ShmFlags::SHM_HUGETLB) { 264 kerror!("shmget: not support huge page"); 265 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 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 /// 失败:错误码 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: PageFlags<MMArch> = 328 PageFlags::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().region().start() != vaddr { 355 return Err(SystemError::EINVAL); 356 } 357 358 // 验证用户虚拟内存区域是否有效 359 let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?; 360 361 // 必须在取消映射前获取到PageFlags 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_mut(&phys.phys_address()) 390 .insert_vma(vma.clone()); 391 392 phys = phys.next(); 393 virt = virt.next(); 394 } 395 396 // 更新vma的映射状态 397 vma.lock().set_mapped(true); 398 399 vaddr.data() 400 } 401 }; 402 403 // 更新最后一次连接时间 404 kernel_shm.update_atim(); 405 406 Ok(r) 407 } 408 409 /// # SYS_SHMDT系统调用函数,用于取消对共享内存的连接 410 /// 411 /// ## 参数 412 /// 413 /// - `vaddr`: 需要取消映射的虚拟内存区域起始地址 414 /// 415 /// ## 返回值 416 /// 417 /// 成功:0 418 /// 失败:错误码 419 pub fn shmdt(vaddr: VirtAddr) -> Result<usize, SystemError> { 420 let current_address_space = AddressSpace::current()?; 421 let mut address_write_guard = current_address_space.write(); 422 423 // 获取vma 424 let vma = address_write_guard 425 .mappings 426 .contains(vaddr) 427 .ok_or(SystemError::EINVAL)?; 428 429 // 判断vaddr是否为起始地址 430 if vma.lock().region().start() != vaddr { 431 return Err(SystemError::EINVAL); 432 } 433 434 // 获取映射的物理地址 435 let paddr = address_write_guard 436 .user_mapper 437 .utable 438 .translate(vaddr) 439 .ok_or(SystemError::EINVAL)? 440 .0; 441 442 // 如果物理页的shm_id为None,代表不是共享页 443 let page_manager_guard = page_manager_lock_irqsave(); 444 let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?; 445 let shm_id = page.shm_id().ok_or(SystemError::EINVAL)?; 446 drop(page_manager_guard); 447 448 // 获取对应共享页管理信息 449 let mut shm_manager_guard = shm_manager_lock(); 450 let kernel_shm = shm_manager_guard 451 .get_mut(&shm_id) 452 .ok_or(SystemError::EINVAL)?; 453 // 更新最后一次断开连接时间 454 kernel_shm.update_dtim(); 455 drop(shm_manager_guard); 456 457 // 取消映射 458 let flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 459 vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); 460 461 return Ok(0); 462 } 463 464 /// # SYS_SHMCTL系统调用函数,用于管理共享内存段 465 /// 466 /// ## 参数 467 /// 468 /// - `id`: 共享内存id 469 /// - `cmd`: 操作码 470 /// - `user_buf`: 用户缓冲区 471 /// - `from_user`: buf_vaddr是否来自用户地址空间 472 /// 473 /// ## 返回值 474 /// 475 /// 成功:0 476 /// 失败:错误码 477 pub fn shmctl( 478 id: ShmId, 479 cmd: ShmCtlCmd, 480 user_buf: *const u8, 481 from_user: bool, 482 ) -> Result<usize, SystemError> { 483 let mut shm_manager_guard = shm_manager_lock(); 484 485 match cmd { 486 // 查看共享内存元信息 487 ShmCtlCmd::IpcInfo => shm_manager_guard.ipc_info(user_buf, from_user), 488 // 查看共享内存使用信息 489 ShmCtlCmd::ShmInfo => shm_manager_guard.shm_info(user_buf, from_user), 490 // 查看id对应的共享内存信息 491 ShmCtlCmd::ShmStat | ShmCtlCmd::ShmtStatAny | ShmCtlCmd::IpcStat => { 492 shm_manager_guard.shm_stat(id, cmd, user_buf, from_user) 493 } 494 // 设置KernIpcPerm 495 ShmCtlCmd::IpcSet => shm_manager_guard.ipc_set(id, user_buf, from_user), 496 // 将共享内存段设置为可回收状态 497 ShmCtlCmd::IpcRmid => shm_manager_guard.ipc_rmid(id), 498 // 锁住共享内存段,不允许内存置换 499 ShmCtlCmd::ShmLock => shm_manager_guard.shm_lock(id), 500 // 解锁共享内存段,允许内存置换 501 ShmCtlCmd::ShmUnlock => shm_manager_guard.shm_unlock(id), 502 // 无效操作码 503 ShmCtlCmd::Default => Err(SystemError::EINVAL), 504 } 505 } 506 } 507