Signals
SEGV信號的使用
據我了解,
SEGV
作業系統會發送一個信號來通知程序它已嘗試進行非法記憶體訪問。但我注意到也可以SEGV
從另一個程序(例如kill -s SEGV pid
)向一個程序發送信號。因此我想知道,能夠向
SEGV
另一個程序發送信號有什麼用?此外,是否有一個程序知道
SEGV
信號是由作業系統還是由另一個程序發送的?
因此我想知道,能夠將 SEGV 信號發送到另一個程序有什麼用?
我想有人可以手動發送它進行測試。但是即使最初沒有想到它的用途,我們也不知道是否有人會提出用途,然後任意限制就會成為阻礙。
此外,是否有一個程序知道 SEGV 信號是由作業系統還是由另一個程序發送的?
是的,正如Catch which user sent kill signal
sigaction()
中提到的,使用標誌設置的信號處理程序可以從結構SA_SIGINFO
中讀取許多細節。siginfo_t
這些包含發送信號的原因 (si_code
),如果適用,則包含發送使用者和 PID (si_uid
,si_pid
)。請參閱手冊頁:https ://man7.org/linux/man-pages/man2/sigaction.2.html
這是一個簡單的測試程序,它為 SIGSEGV 設置一個處理程序並將其發送給自己,首先使用
kill()
然後觸發無效的記憶體訪問:#include <sys/types.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void action(int sig, siginfo_t *si, void *p) { printf("sig: %d\n", sig); printf("si_signo: %d\n", si->si_signo); char *reason = "?"; switch (si->si_code) { case SI_USER: reason = "Signal sent by user"; break; case SI_TKILL: reason = "Signal sent by user (tkill)"; break; case SI_KERNEL: reason = "Signal sent by kernel"; break; case SEGV_MAPERR: reason = "SIGSEGV - Address not mapped to object"; break; case SEGV_ACCERR: reason = "SIGSEGV - Invalid permissions for mapped object"; break; } printf("si_code: %d (%s)\n", si->si_code, reason); printf("si_pid: %d\n", (int) si->si_pid); printf("si_uid: %d\n", (int) si->si_uid); printf("si_addr: 0x%016lx\n", (unsigned long) si->si_addr); if (si->si_code != SI_USER && si->si_code != SI_TKILL) { // if it's an actual error, exit instead of // returning to repeat the error _exit(1); } } int main(void) { struct sigaction sa = {0}; sa.sa_sigaction = action; sa.sa_flags = SA_SIGINFO; int ret = sigaction(SIGSEGV, &sa, NULL); if (ret == -1) { perror("sigaction"); exit(1); } printf("raising SIGSEGV manually\n"); kill(getpid(), SIGSEGV); printf("\n"); printf("trying to trigger SIGSEGV\n"); volatile int *p = (int *) 0xdeadbeef; (void) *p; }
我的系統上的輸出是:
raising SIGSEGV manually sig: 11 si_signo: 11 si_code: 0 (Signal sent by user) si_pid: 13868 si_uid: 1000 si_addr: 0x000003e80000362c trying to trigger SIGSEGV sig: 11 si_signo: 11 si_code: 1 (SIGSEGV - Address not mapped to object) si_pid: -559038737 si_uid: 0 si_addr: 0x00000000deadbeef
(請注意,某些不適用於相關案例的欄位包含垃圾。)