2013-06-28 35 views
3

在通過void (*sa_sigaction)(int, siginfo_t *, void *);安裝的信號處理程序中,如何判斷SIGILL是源自非法指令還是發送SIGILL的某個進程?我查看了siginfo_t的si_pid,但是如果遇到非法指令,這似乎是未初始化的,所以我不能根據它做出決定。 - 當然,我正在尋找一種最簡單便攜的解決方案,而不是閱讀si_addr的指令代碼並試圖確定它是否合法。如何判斷SIGILL是源自非法指令還是kill -ILL?

+2

爲什麼要這麼做? – ctn

+0

...爲了找到一個Xenomai線程終止的原因,其中gdb表示「程序以信號4終止,非法指令」,但是在$ pc 核心文件中有合法的分支指令。 – Armali

回答

6

A 善意 SIGILL將具有其中一個ILL_值(例如,IL_ILLADR)的si_code。用戶請求的SIGILL將具有其中一個SI_值(通常爲SI_USER)的si_code

relevant POSIX values是:

[Kernel-generated] 
ILL_ILLOPC Illegal opcode. 
ILL_ILLOPN Illegal operand. 
ILL_ILLADR Illegal addressing mode. 
ILL_ILLTRP Illegal trap. 
ILL_PRVOPC Privileged opcode. 
ILL_PRVREG Privileged register. 
ILL_COPROC Coprocessor error. 
ILL_BADSTK Internal stack error. 

[User-requested] 
SI_USER  Signal sent by kill(). 
SI_QUEUE Signal sent by the sigqueue(). 
SI_TIMER Signal generated by expiration of a timer set by timer_settime(). 
SI_ASYNCIO Signal generated by completion of an asynchronous I/O request. 
SI_MESGQ Signal generated by arrival of a message on an empty message queue. 

例如,recipe in this question給我ILL_ILLOPN,而kill(1)kill(2)給我零(SI_USER)。

當然,您的實現可能會將值添加到POSIX列表中。歷史上,user- or process-generated si_code values were <= 0,這仍然是相當普遍的。你的實現也可能有一個方便的宏來幫助你。例如,Linux提供:

#define SI_FROMUSER(siptr)  ((siptr)->si_code <= 0) 
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0) 
+0

實際上,'kill'生成的信號的'si_code'應該是'SI_USER',它通常是0,但在某些系統上可能是其他的東西。它將與所有ILL_值不同。 –

+0

@ChrisDodd,謝謝,更新。 – pilcrow

+0

@nos,是的,但是OP的測試顯示他不能單靠這個領域。 – pilcrow

相關問題