系統呼叫
syscall_define4(rt_sigprocmask, int, how, sigset_t __user *, nset,
sigset_t __user *, oset, size_t, sigsetsize) //堵塞或者撤銷堵塞某些訊號
=>sigprocmask
syscall_define3(sigprocmask, int, how, old_sigset_t __user *, nset,
old_sigset_t __user *, oset)
=>sigaddsetmask(&new_blocked, new_set);
syscall_define2(signal, int, sig, __sighandler_t, handler)//設定訊號處理函式
=>do_sigaction(sig, &new_sa, &old_sa);
核心訊號觸發,詳見linux記憶體管理部分,do_page_fault
核心訊號處理
do_notify_resume
=>do_signal
=>signr = get_signal_to_deliver(&info, &ka, regs, null);
=>for (;;)
=>signr = dequeue_signal(current, ¤t->blocked, info);//pending佇列取乙個訊號
=>if (!signr)//隊列為空時退出
break; /* will return 0 */
=>if (ka->sa.sa_handler != sig_dfl)
=>if (sig_kernel_coredump(signr))//如果訊號比較嚴重,則coredump,增加除錯資訊
do_coredump(info->si_signo, info->si_signo, regs);
=>retval = binfmt->core_dump(&cprm);
static struct linux_binfmt elf_format = ;
#ifdef config_elf_core
static int elf_core_dump(struct coredump_params *cprm);
#else
#define elf_core_dump null
#endif
=>do_group_exit(info->si_signo);
=>handle_signal(signr, &info, &ka, oldset, regs)
=>ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, ka, regs, sig, oldset, info);
=>setup_rt_frame //arch\mips\kernel): .setup_rt_frame = setup_rt_frame,
=>frame = get_sigframe(ka, regs, sizeof(*frame));
=>/* create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info);//設定訊號處理函式棧幀
=>regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;//掛接訊號處理函式,handle_signal返回時呼叫sa_handler
核心在允許程序恢復使用者態執行之前,檢測程序tif_sigpending標誌的數值,每當核心處理完1個中斷/異常時,就檢查是否存在程序掛起訊號
例子如下:
ret_from_exception
=>movl ti_flags(%ebp), %ecx
=>andl $_tif_work_mask, %ecx # is there any work to be done on
# int/exception return?
=>jne work_pending
=>testb $_tif_need_resched, %cl
=>jz work_notifysig
=>xorl %edx, %edx
=>call do_notify_resume
=>if (thread_info_flags & (_tif_sigpending | _tif_restore_sigmask))
do_signal(regs);
=>clear_thread_flag(tif_iret);
=>jmp resume_userspace_sig
監控程序:可以通過epoll與所有程序通訊,一旦通訊是吧,可以呼叫waitpid獲取狀態
void do_notify_resume(struct pt_regs *regs, void *_unused,
__u32 thread_info_flags)
/* deal with pending signal delivery */
if (thread_info_flags & (_tif_sigpending | _tif_restore_sigmask))
do_signal(regs);
=>handle_signal(signr, &info, &ka, oldset, regs)
=>ret = setup_frame(sig, ka, oldset, regs);
=>printk("sig deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->eip, frame->pretcode);
clear_thread_flag(tif_iret);
}
文章參考
linux訊號(signal) 機制分析
如何模擬發訊號給程序
利用sigpending,sigismember檢測訊號是否被掛起
該篇文章講sigint替換成sigill,然後將main函式的主體增加while ;做實驗kill -ill 程序號,核心會進入do_signal函式
linux signal實現**分析
linux signal 那些事兒 (3) 部落格不錯
父子程序互發訊號
include include include include includeint handler int signo return 0 int main if signal sigusr2,handler sig err ppid getpid 得到父程序的程序id if cpid fork 0...
python併發 訊號量
訊號量通常用於保護數量有限的資源,例如資料庫伺服器。在資源數量固定的任何情況下,都應該使用有界訊號量。在生成任何工作執行緒前,應該在主線程中初始化訊號量。工作執行緒生成後,當需要連線伺服器時,這些執行緒將呼叫訊號量的 acquire 和 release 方法 使用有界訊號量能減少這種程式設計錯誤 訊...
Ubuntu linux下的C語言開發(訊號處理)
訊號處理是linux程式的乙個特色。用訊號處理來模擬作業系統的中斷功能,對於我們這些系統程式設計師來說是最好的乙個選擇了。要想使用訊號處理功能,你要做的就是填寫乙個訊號處理函式即可。一旦程序有待處理的訊號處理,那麼程序就會立即進行處理。include include include int valu...