1 use core::{ffi::c_void, intrinsics::size_of, ptr::read_volatile, sync::atomic::compiler_fence}; 2 3 use crate::{ 4 arch::x86_64::{ 5 asm::{bitops::ffz, current::current_pcb, ptrace::user_mode}, 6 interrupt::sti, 7 }, 8 include::bindings::bindings::{ 9 pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs, 10 spinlock_t, verify_area, EINVAL, ENOTSUP, EPERM, ESRCH, PF_EXITING, PF_KTHREAD, 11 PF_SIGNALED, PF_WAKEKILL, PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR, 12 }, 13 ipc::signal_types::sigset_add, 14 kBUG, kdebug, kerror, kwarn, 15 libs::{ 16 ffi_convert::FFIBind2Rust, 17 spinlock::{ 18 spin_is_locked, spin_lock_irq, spin_lock_irqsave, spin_unlock_irq, 19 spin_unlock_irqrestore, 20 }, 21 }, 22 println, 23 process::{ 24 pid::PidType, 25 process::{process_is_stopped, process_kick, process_wake_up_state}, 26 }, 27 }; 28 29 use super::signal_types::{ 30 si_code_val, sigaction, sigaction__union_u, sigcontext, sigframe, sighand_struct, siginfo, 31 signal_struct, sigpending, sigset_clear, sigset_del, sigset_t, SignalNumber, MAX_SIG_NUM, 32 SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT, 33 }; 34 35 use super::signal_types::{__siginfo_union, __siginfo_union_data}; 36 37 /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位) 38 pub static DEFAULT_SIGACTION: sigaction = sigaction { 39 _u: sigaction__union_u { _sa_handler: None }, 40 sa_flags: SA_FLAG_DFL, 41 sa_mask: 0, 42 sa_restorer: None, 43 }; 44 45 /// 默认的“忽略信号”的sigaction 46 #[allow(dead_code)] 47 pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction { 48 _u: sigaction__union_u { _sa_handler: None }, 49 sa_flags: SA_FLAG_IGN, 50 sa_mask: 0, 51 sa_restorer: None, 52 }; 53 54 /// @brief kill系统调用,向指定的进程发送信号 55 /// @param regs->r8 pid 要接收信号的进程id 56 /// @param regs->r9 sig 信号 57 #[no_mangle] 58 pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 { 59 println!( 60 "sys kill, target pid={}, file={}, line={}", 61 regs.r8, 62 file!(), 63 line!() 64 ); 65 66 let pid: pid_t = regs.r8 as pid_t; 67 let sig: SignalNumber = SignalNumber::from(regs.r9 as i32); 68 if sig == SignalNumber::INVALID { 69 // 传入的signal数值不合法 70 kwarn!("Not a valid signal number"); 71 return (-(EINVAL as i64)) as u64; 72 } 73 74 // 初始化signal info 75 let mut info = siginfo { 76 _sinfo: __siginfo_union { 77 data: __siginfo_union_data { 78 si_signo: sig as i32, 79 si_code: si_code_val::SI_USER as i32, 80 si_errno: 0, 81 reserved: 0, 82 _sifields: super::signal_types::__sifields { 83 _kill: super::signal_types::__sifields__kill { _pid: pid }, 84 }, 85 }, 86 }, 87 }; 88 compiler_fence(core::sync::atomic::Ordering::SeqCst); 89 90 let retval = signal_kill_something_info(sig, Some(&mut info), pid) as u64; 91 92 compiler_fence(core::sync::atomic::Ordering::SeqCst); 93 return retval; 94 } 95 96 /// 通过kill的方式向目标进程发送信号 97 /// @param sig 要发送的信号 98 /// @param info 要发送的信息 99 /// @param pid 进程id(目前只支持pid>0) 100 fn signal_kill_something_info(sig: SignalNumber, info: Option<&mut siginfo>, pid: pid_t) -> i32 { 101 // 暂时不支持特殊的kill操作 102 if pid <= 0 { 103 kwarn!("Kill operation not support: pid={}", pid); 104 return -(ENOTSUP as i32); 105 } 106 107 // kill单个进程 108 return signal_kill_proc_info(sig, info, pid); 109 } 110 111 fn signal_kill_proc_info(sig: SignalNumber, info: Option<&mut siginfo>, pid: pid_t) -> i32 { 112 let mut retval: i32 = -(ESRCH as i32); 113 114 // step1: 当进程管理模块拥有pcblist_lock之后,对其加锁 115 116 // step2: 根据pid找到pcb 117 let pcb = unsafe { process_find_pcb_by_pid(pid).as_mut() }; 118 119 if pcb.is_none() { 120 kwarn!("No such process."); 121 return retval; 122 } 123 124 // println!("Target pcb = {:?}", pcb.as_ref().unwrap()); 125 compiler_fence(core::sync::atomic::Ordering::SeqCst); 126 // step3: 调用signal_send_sig_info函数,发送信息 127 retval = signal_send_sig_info(sig, info, pcb.unwrap()); 128 compiler_fence(core::sync::atomic::Ordering::SeqCst); 129 // step4: 解锁 130 return retval; 131 } 132 133 /// @brief 验证信号的值是否在范围内 134 #[inline] 135 fn verify_signal(sig: SignalNumber) -> bool { 136 return if (sig as i32) <= MAX_SIG_NUM { 137 true 138 } else { 139 false 140 }; 141 } 142 143 /// @brief 在发送信号给指定的进程前,做一些权限检查. 检查是否有权限发送 144 /// @param sig 要发送的信号 145 /// @param info 要发送的信息 146 /// @param target_pcb 信号的接收者 147 fn signal_send_sig_info( 148 sig: SignalNumber, 149 info: Option<&mut siginfo>, 150 target_pcb: &mut process_control_block, 151 ) -> i32 { 152 // kdebug!("signal_send_sig_info"); 153 // 检查sig是否符合要求,如果不符合要求,则退出。 154 if !verify_signal(sig) { 155 return -(EINVAL as i32); 156 } 157 158 // 信号符合要求,可以发送 159 160 let mut retval = -(ESRCH as i32); 161 let mut flags: u64 = 0; 162 // 如果上锁成功,则发送信号 163 if !lock_process_sighand(target_pcb, &mut flags).is_none() { 164 compiler_fence(core::sync::atomic::Ordering::SeqCst); 165 // 发送信号 166 retval = send_signal_locked(sig, info, target_pcb, PidType::PID); 167 compiler_fence(core::sync::atomic::Ordering::SeqCst); 168 // kdebug!("flags=0x{:016x}", flags); 169 // 对sighand放锁 170 unlock_process_sighand(target_pcb, flags); 171 } 172 return retval; 173 } 174 175 /// @brief 对pcb的sighand结构体中的siglock进行加锁,并关闭中断 176 /// @param pcb 目标pcb 177 /// @param flags 用来保存rflags的变量 178 /// @return 指向sighand_struct的可变引用 179 fn lock_process_sighand<'a>( 180 pcb: &'a mut process_control_block, 181 flags: &mut u64, 182 ) -> Option<&'a mut sighand_struct> { 183 // kdebug!("lock_process_sighand"); 184 185 let sighand_ptr = sighand_struct::convert_mut(unsafe { &mut *pcb.sighand }); 186 // kdebug!("sighand_ptr={:?}", &sighand_ptr); 187 if !sighand_ptr.is_some() { 188 kBUG!("Sighand ptr of process {pid} is NULL!", pid = pcb.pid); 189 return None; 190 } 191 192 let lock = { &mut sighand_ptr.unwrap().siglock }; 193 194 spin_lock_irqsave(lock, flags); 195 let ret = unsafe { ((*pcb).sighand as *mut sighand_struct).as_mut() }; 196 197 return ret; 198 } 199 200 /// @brief 对pcb的sighand结构体中的siglock进行放锁,并恢复之前存储的rflags 201 /// @param pcb 目标pcb 202 /// @param flags 用来保存rflags的变量,将这个值恢复到rflags寄存器中 203 fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) { 204 let lock = unsafe { &mut (*pcb.sighand).siglock }; 205 206 spin_unlock_irqrestore(lock, &flags); 207 } 208 209 /// @brief 判断是否需要强制发送信号,然后发送信号 210 /// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。 211 /// 212 /// @return i32 错误码 213 fn send_signal_locked( 214 sig: SignalNumber, 215 info: Option<&mut siginfo>, 216 pcb: &mut process_control_block, 217 pt: PidType, 218 ) -> i32 { 219 // 是否强制发送信号 220 let mut force_send = false; 221 // signal的信息为空 222 if info.is_none() { 223 // todo: 判断signal是否来自于一个祖先进程的namespace,如果是,则强制发送信号 224 } else { 225 force_send = unsafe { info.as_ref().unwrap()._sinfo.data.si_code } 226 == (si_code_val::SI_KERNEL as i32); 227 } 228 229 // kdebug!("force send={}", force_send); 230 231 return __send_signal_locked(sig, info, pcb, pt, force_send); 232 } 233 234 /// @brief 发送信号 235 /// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。 236 /// 237 /// @param sig 信号 238 /// @param _info 信号携带的信息 239 /// @param pcb 目标进程的pcb 240 /// @param pt siginfo结构体中,pid字段代表的含义 241 /// @return i32 错误码 242 fn __send_signal_locked( 243 sig: SignalNumber, 244 _info: Option<&mut siginfo>, 245 pcb: &mut process_control_block, 246 pt: PidType, 247 _force_send: bool, 248 ) -> i32 { 249 // kdebug!("__send_signal_locked"); 250 let mut retval = 0; 251 252 // 判断该进入该函数时,是否已经持有了锁 253 assert!(spin_is_locked(unsafe { &(*pcb.sighand).siglock })); 254 255 let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending); 256 compiler_fence(core::sync::atomic::Ordering::SeqCst); 257 // 如果是kill或者目标pcb是内核线程,则无需获取sigqueue,直接发送信号即可 258 if sig == SignalNumber::SIGKILL || (pcb.flags & (PF_KTHREAD as u64)) != 0 { 259 complete_signal(sig, pcb, pt); 260 } else { 261 // todo: 如果是其他信号,则加入到sigqueue内,然后complete_signal 262 retval = -(ENOTSUP as i32); 263 } 264 compiler_fence(core::sync::atomic::Ordering::SeqCst); 265 return retval; 266 } 267 268 /// @brief 将信号添加到目标进程的sig_pending。在引入进程组后,本函数还将负责把信号传递给整个进程组。 269 /// 270 /// @param sig 信号 271 /// @param pcb 目标pcb 272 /// @param pt siginfo结构体中,pid字段代表的含义 273 fn complete_signal(sig: SignalNumber, pcb: &mut process_control_block, pt: PidType) { 274 // kdebug!("complete_signal"); 275 276 // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify) 277 // 将这个信号加到目标进程的sig_pending中 278 sigset_add( 279 sigset_t::convert_mut(&mut pcb.sig_pending.signal).unwrap(), 280 sig, 281 ); 282 compiler_fence(core::sync::atomic::Ordering::SeqCst); 283 // ===== 寻找需要wakeup的目标进程 ===== 284 // 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。 285 // todo: 当引入进程组的概念后,需要完善这里,使得它能寻找一个目标进程来唤醒,接着执行信号处理的操作。 286 287 let _signal: Option<&mut signal_struct> = signal_struct::convert_mut(pcb.signal); 288 289 let mut _target: Option<&mut process_control_block> = None; 290 291 // 判断目标进程是否想接收这个信号 292 if wants_signal(sig, pcb) { 293 _target = Some(pcb); 294 } else if pt == PidType::PID { 295 /* 296 * There is just one thread and it does not need to be woken. 297 * It will dequeue unblocked signals before it runs again. 298 */ 299 return; 300 } else { 301 /* 302 * Otherwise try to find a suitable thread. 303 * 由于目前每个进程只有1个线程,因此当前情况可以返回。信号队列的dequeue操作不需要考虑同步阻塞的问题。 304 */ 305 return; 306 } 307 308 // todo:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。 309 // todo!(); 310 compiler_fence(core::sync::atomic::Ordering::SeqCst); 311 // todo: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。 312 if _target.is_some() { 313 signal_wake_up(pcb, sig == SignalNumber::SIGKILL); 314 } 315 } 316 317 /// @brief 本函数用于检测指定的进程是否想要接收SIG这个信号。 318 /// 当我们对于进程组中的所有进程都运行了这个检查之后,我们将可以找到组内愿意接收信号的进程。 319 /// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。 320 #[inline] 321 fn wants_signal(sig: SignalNumber, pcb: &process_control_block) -> bool { 322 // 如果改进程屏蔽了这个signal,则不能接收 323 if sig_is_member(sigset_t::convert_ref(&pcb.sig_blocked).unwrap(), sig) { 324 return false; 325 } 326 327 // 如果进程正在退出,则不能接收信号 328 if (pcb.flags & (PF_EXITING as u64)) > 0 { 329 return false; 330 } 331 332 if sig == SignalNumber::SIGKILL { 333 return true; 334 } 335 336 if process_is_stopped(pcb) { 337 return false; 338 } 339 340 // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项 341 342 // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true 343 return !has_sig_pending(pcb); 344 } 345 346 /// @brief 判断指定的信号在sigset中的对应位是否被置位 347 /// @return true: 给定的信号在sigset中被置位 348 /// @return false: 给定的信号在sigset中没有被置位 349 #[inline] 350 fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool { 351 return if 1 & (set >> ((_sig as u32) - 1)) != 0 { 352 true 353 } else { 354 false 355 }; 356 } 357 358 /// @brief 判断signal的处理是否可能使得整个进程组退出 359 /// @return true 可能会导致退出(不一定) 360 #[allow(dead_code)] 361 #[inline] 362 fn sig_fatal(pcb: &process_control_block, sig: SignalNumber) -> bool { 363 let handler = unsafe { 364 sighand_struct::convert_ref(pcb.sighand).unwrap().action[(sig as usize) - 1] 365 ._u 366 ._sa_handler 367 }; 368 369 // 如果handler是空,采用默认函数,signal处理可能会导致进程退出。 370 if handler.is_none() { 371 return true; 372 } else { 373 return false; 374 } 375 376 // todo: 参照linux的sig_fatal实现完整功能 377 } 378 379 /// @brief 判断某个进程是否有信号正在等待处理 380 #[inline] 381 fn has_sig_pending(pcb: &process_control_block) -> bool { 382 let ptr = &sigpending::convert_ref(&(*pcb).sig_pending).unwrap().signal; 383 if unsafe { read_volatile(ptr) } != 0 { 384 return true; 385 } else { 386 return false; 387 } 388 } 389 390 #[inline] 391 fn signal_wake_up(pcb: &mut process_control_block, fatal: bool) { 392 // kdebug!("signal_wake_up"); 393 let mut state: u64 = 0; 394 if fatal { 395 state = PF_WAKEKILL as u64; 396 } 397 signal_wake_up_state(pcb, state); 398 } 399 400 fn signal_wake_up_state(pcb: &mut process_control_block, state: u64) { 401 assert!(spin_is_locked(&unsafe { (*pcb.sighand).siglock })); 402 // todo: 设置线程结构体的标志位为TIF_SIGPENDING 403 compiler_fence(core::sync::atomic::Ordering::SeqCst); 404 // 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核 405 if !process_wake_up_state(pcb, state | (PROC_INTERRUPTIBLE as u64)) { 406 process_kick(pcb); 407 } 408 compiler_fence(core::sync::atomic::Ordering::SeqCst); 409 } 410 411 /// @brief 信号处理函数。该函数在进程退出内核态的时候会被调用,且调用前会关闭中断。 412 #[no_mangle] 413 pub extern "C" fn do_signal(regs: &mut pt_regs) { 414 // 检查sigpending是否为0 415 if current_pcb().sig_pending.signal == 0 || (!user_mode(regs)) { 416 // 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回 417 sti(); 418 return; 419 } 420 421 // 做完上面的检查后,开中断 422 sti(); 423 // return; 424 // kdebug!("do_signal"); 425 let oldset = current_pcb().sig_blocked; 426 loop { 427 let (sig_number, info, ka) = get_signal_to_deliver(regs.clone()); 428 // 所有的信号都处理完了 429 if sig_number == SignalNumber::INVALID { 430 return; 431 } 432 kdebug!( 433 "To handle signal [{}] for pid:{}", 434 sig_number as i32, 435 current_pcb().pid 436 ); 437 let res = handle_signal(sig_number, ka.unwrap(), &info.unwrap(), &oldset, regs); 438 if res.is_err() { 439 kerror!( 440 "Error occurred when handling signal: {}, pid={}, errcode={}", 441 sig_number as i32, 442 current_pcb().pid, 443 res.unwrap_err() 444 ); 445 } 446 } 447 } 448 449 /// @brief 获取要被发送的信号的signumber, siginfo, 以及对应的sigaction结构体 450 fn get_signal_to_deliver( 451 _regs: pt_regs, 452 ) -> ( 453 SignalNumber, 454 Option<siginfo>, 455 Option<&'static mut sigaction>, 456 ) { 457 let mut info: Option<siginfo>; 458 let ka: Option<&mut sigaction>; 459 let mut sig_number; 460 let sighand: &mut sighand_struct; 461 462 { 463 let _tmp = sighand_struct::convert_mut(current_pcb().sighand); 464 if let Some(i) = _tmp { 465 sighand = i; 466 } else { 467 panic!("Sighand is NULL! pid={}", current_pcb().pid); 468 } 469 } 470 471 spin_lock_irq(&mut sighand.siglock); 472 loop { 473 (sig_number, info) = 474 dequeue_signal(sigset_t::convert_mut(&mut current_pcb().sig_blocked).unwrap()); 475 476 // 如果信号非法,则直接返回 477 if sig_number == SignalNumber::INVALID { 478 spin_unlock_irq(unsafe { (&mut (*current_pcb().sighand).siglock) as *mut spinlock_t }); 479 return (sig_number, None, None); 480 } 481 482 // 获取指向sigaction结构体的引用 483 let hand = sighand_struct::convert_mut(current_pcb().sighand).unwrap(); 484 // kdebug!("hand=0x{:018x}", hand as *const sighand_struct as usize); 485 let tmp_ka = &mut hand.action[sig_number as usize - 1]; 486 487 // 如果当前动作是忽略这个信号,则不管它了。 488 if (tmp_ka.sa_flags & SA_FLAG_IGN) != 0 { 489 continue; 490 } else if (tmp_ka.sa_flags & SA_FLAG_DFL) == 0 { 491 // 当前不采用默认的信号处理函数 492 ka = Some(tmp_ka); 493 break; 494 } 495 kdebug!( 496 "Use default handler to handle signal [{}] for pid {}", 497 sig_number as i32, 498 current_pcb().pid 499 ); 500 // ===== 经过上面的判断,如果能走到这一步,就意味着我们采用默认的信号处理函数来处理这个信号 ===== 501 spin_unlock_irq(&mut sighand.siglock); 502 // 标记当前进程由于信号而退出 503 current_pcb().flags |= PF_SIGNALED as u64; 504 505 // 执行进程的退出动作 506 unsafe { process_do_exit(info.unwrap()._sinfo.data.si_signo as u64) }; 507 /* NOT REACHED 这部分代码将不会到达 */ 508 } 509 spin_unlock_irq(&mut sighand.siglock); 510 return (sig_number, info, ka); 511 } 512 513 /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号) 514 /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock 515 fn dequeue_signal(sig_mask: &mut sigset_t) -> (SignalNumber, Option<siginfo>) { 516 // kdebug!("dequeue signal"); 517 // 获取下一个要处理的信号的编号 518 let sig = next_signal( 519 sigpending::convert_ref(&(current_pcb().sig_pending)).unwrap(), 520 sig_mask, 521 ); 522 523 let info: Option<siginfo>; 524 if sig != SignalNumber::INVALID { 525 // 如果下一个要处理的信号是合法的,则收集其siginfo 526 info = Some(collect_signal( 527 sig, 528 sigpending::convert_mut(&mut current_pcb().sig_pending).unwrap(), 529 )); 530 } else { 531 info = None; 532 } 533 534 // 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位 535 recalc_sigpending(); 536 return (sig, info); 537 } 538 539 /// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高) 540 /// 541 /// @param pending 等待处理的信号 542 /// @param sig_mask 屏蔽了的信号 543 /// @return i32 下一个要处理的信号的number. 如果为0,则无效 544 fn next_signal(pending: &sigpending, sig_mask: &sigset_t) -> SignalNumber { 545 let mut sig = SignalNumber::INVALID; 546 547 let s = pending.signal; 548 let m = *sig_mask; 549 550 // 获取第一个待处理的信号的号码 551 let x = s & (!m); 552 if x != 0 { 553 sig = SignalNumber::from(ffz(!x) + 1); 554 return sig; 555 } 556 557 // 暂时只支持64种信号信号 558 assert_eq!(_NSIG_U64_CNT, 1); 559 560 return sig; 561 } 562 563 /// @brief 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位 564 fn recalc_sigpending() { 565 // todo: 566 } 567 568 /// @brief 收集信号的信息 569 /// 570 /// @param sig 要收集的信号的信息 571 /// @param pending 信号的排队等待标志 572 /// @return siginfo 信号的信息 573 fn collect_signal(sig: SignalNumber, pending: &mut sigpending) -> siginfo { 574 let (info, still_pending) = unsafe { pending.queue.as_mut() } 575 .unwrap() 576 .find_and_delete(sig); 577 578 // 如果没有仍在等待的信号,则清除pending位 579 if !still_pending { 580 sigset_del(&mut pending.signal, sig); 581 } 582 583 if info.is_some() { 584 return info.unwrap(); 585 } else { 586 // 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。 587 let mut ret = siginfo::new(sig, 0, si_code_val::SI_USER); 588 ret._sinfo.data._sifields._kill._pid = 0; 589 return ret; 590 } 591 } 592 593 /// @brief 真正发送signal,执行自定义的处理函数 594 /// 595 /// @param sig 信号number 596 /// @param ka 信号响应动作 597 /// @param info 信号信息 598 /// @param oldset 599 /// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝 600 /// 601 /// @return Result<0,i32> 若Error, 则返回错误码,否则返回Ok(0) 602 fn handle_signal( 603 sig: SignalNumber, 604 ka: &mut sigaction, 605 info: &siginfo, 606 oldset: &sigset_t, 607 regs: &mut pt_regs, 608 ) -> Result<i32, i32> { 609 // 设置栈帧 610 let retval = setup_frame(sig, ka, info, oldset, regs); 611 if retval.is_err() { 612 return retval; 613 } 614 return Ok(0); 615 } 616 617 /// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。 618 /// 619 /// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧 620 fn setup_frame( 621 sig: SignalNumber, 622 ka: &mut sigaction, 623 info: &siginfo, 624 oldset: &sigset_t, 625 regs: &mut pt_regs, 626 ) -> Result<i32, i32> { 627 let mut err = 0; 628 let frame: *mut sigframe = get_stack(ka, ®s, size_of::<sigframe>()); 629 630 // 要求这个frame的地址位于用户空间,因此进行校验 631 let access_check_ok = unsafe { verify_area(frame as u64, size_of::<sigframe>() as u64) }; 632 if !access_check_ok { 633 // 如果地址区域位于内核空间,则直接报错 634 // todo: 生成一个sigsegv 635 kerror!("In setup frame: access check failed"); 636 return Err(-(EPERM as i32)); 637 } 638 639 unsafe { 640 (*frame).arg0 = sig as u64; 641 (*frame).arg1 = &((*frame).info) as *const siginfo as usize; 642 (*frame).arg2 = &((*frame).context) as *const sigcontext as usize; 643 (*frame).handler = ka._u._sa_handler.unwrap() as *mut core::ffi::c_void; 644 } 645 646 // 将siginfo拷贝到用户栈 647 err |= copy_siginfo_to_user(unsafe { &mut (*frame).info }, info).unwrap_or(1); 648 649 // todo: 拷贝处理程序备用栈的地址、大小、ss_flags 650 651 err |= setup_sigcontext(unsafe { &mut (*frame).context }, oldset, ®s).unwrap_or(1); 652 653 // 为了与Linux的兼容性,64位程序必须由用户自行指定restorer 654 if ka.sa_flags & SA_FLAG_RESTORER != 0 { 655 unsafe { 656 (*frame).ret_code_ptr = 657 (&mut ka.sa_restorer.unwrap()) as *mut unsafe extern "C" fn() as *mut c_void; 658 } 659 } else { 660 kerror!( 661 "pid-{} forgot to set SA_FLAG_RESTORER for signal {}", 662 current_pcb().pid, 663 sig as i32 664 ); 665 err = 1; 666 } 667 if err != 0 { 668 // todo: 在这里生成一个sigsegv,然后core dump 669 return Err(1); 670 } 671 672 regs.rdi = sig as u64; 673 regs.rsi = unsafe { &(*frame).info as *const siginfo as u64 }; 674 regs.rsp = frame as u64; 675 regs.rip = unsafe { ka._u._sa_handler.unwrap() as *const unsafe extern "C" fn() as u64 }; 676 677 // 如果handler位于内核空间 678 if regs.rip >= USER_MAX_LINEAR_ADDR { 679 // 如果当前是SIGSEGV,则采用默认函数处理 680 if sig == SignalNumber::SIGSEGV { 681 ka.sa_flags |= SA_FLAG_DFL; 682 } 683 684 // 将rip设置为0 685 regs.rip = 0; 686 } 687 688 // 设置cs和ds寄存器 689 regs.cs = (USER_CS | 0x3) as u64; 690 regs.ds = (USER_DS | 0x3) as u64; 691 692 return if err == 0 { Ok(0) } else { Err(1) }; 693 } 694 695 #[inline(always)] 696 fn get_stack(_ka: &sigaction, regs: &pt_regs, size: usize) -> *mut sigframe { 697 // 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小 698 let mut rsp: usize = (regs.rsp as usize) - 128 - size; 699 // 按照要求进行对齐 700 rsp &= (-(STACK_ALIGN as i64)) as usize; 701 return rsp as *mut sigframe; 702 } 703 704 /// @brief 将siginfo结构体拷贝到用户栈 705 fn copy_siginfo_to_user(to: *mut siginfo, from: &siginfo) -> Result<i32, i32> { 706 // 验证目标地址是否为用户空间 707 if unsafe { !verify_area(to as u64, size_of::<siginfo>() as u64) } { 708 // 如果目标地址空间不为用户空间,则直接返回错误码 -EPERM 709 return Err(-(EPERM as i32)); 710 } 711 712 let retval: Result<i32, i32> = Ok(0); 713 714 // todo: 将这里按照si_code的类型来分别拷贝不同的信息。 715 // 这里参考linux-2.6.39 网址: http://opengrok.ringotek.cn/xref/linux-2.6.39/arch/ia64/kernel/signal.c#137 716 717 unsafe { 718 (*to)._sinfo.data._sifields._kill._pid = from._sinfo.data._sifields._kill._pid; 719 } 720 721 return retval; 722 } 723 724 /// @brief 设置目标的sigcontext 725 /// 726 /// @param context 要被设置的目标sigcontext 727 /// @param mask 要被暂存的信号mask标志位 728 /// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧 729 fn setup_sigcontext(context: &mut sigcontext, mask: &sigset_t, regs: &pt_regs) -> Result<i32, i32> { 730 let current_thread = current_pcb().thread; 731 732 context.oldmask = *mask; 733 context.regs = regs.clone(); 734 context.trap_num = unsafe { (*current_thread).trap_num }; 735 context.err_code = unsafe { (*current_thread).err_code }; 736 context.cr2 = unsafe { (*current_thread).cr2 }; 737 return Ok(0); 738 } 739 740 /// @brief 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为Default 741 /// 除非某个信号被设置为ignore且force_default为false,否则都不会将其恢复 742 /// 743 /// @param pcb 要被刷新的pcb 744 /// @param force_default 是否强制将sigaction恢复成默认状态 745 pub fn flush_signal_handlers(pcb: *mut process_control_block, force_default: bool) { 746 compiler_fence(core::sync::atomic::Ordering::SeqCst); 747 748 let action = unsafe { &mut (*(*pcb).sighand).action }; 749 for ka in action.iter_mut() { 750 if force_default || (ka.sa_flags != SA_FLAG_IGN) { 751 ka.sa_flags = SA_FLAG_DFL; 752 ka._u._sa_handler = None; 753 } 754 // 清除flags中,除了DFL和IGN以外的所有标志 755 ka.sa_flags &= SA_FLAG_DFL | SA_FLAG_IGN; 756 ka.sa_restorer = None; 757 sigset_clear(&mut ka.sa_mask); 758 compiler_fence(core::sync::atomic::Ordering::SeqCst); 759 } 760 compiler_fence(core::sync::atomic::Ordering::SeqCst); 761 } 762