訊號學習心得 如何模擬發訊號給程序

2021-08-03 13:58:59 字數 3180 閱讀 6210

系統呼叫

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...