SEGV信号的使用

SEGV信号的使用

据我了解,SEGV操作系统发送一个信号来通知进程它已尝试非法内存访问。但我注意到也可以SEGV从另一个进程向一个进程发送信号(例如kill -s SEGV pid)。

因此我想知道,能够SEGV向另一个进程发送信号有什么用?

此外,进程是否可以知道信号是SEGV由操作系统还是另一个进程发送的?

答案1

因此我想知道,能够向另一个进程发送 SEGV 信号有什么用?

我想有人可以手动发送它进行测试。但即使最初没有想到它的用途,我们也永远不知道是否有人会想出一种用途,然后任意的限制就会成为障碍。

此外,进程是否可以知道 SEGV 信号是由操作系统还是另一个进程发送的?

是的,正如中提到的捕获哪个用户发送终止信号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

(请注意,某些不适用于相关案例的字段包含垃圾。)

答案2

Unix 对可以向进程发送哪些信号没有限制。它仅根据进程所有权限制信号。

一般来说,没有办法确定信号的来源。

相关内容