Linux: signal

139 阅读2分钟

sigaction函数

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,
              struct sigaction *oldact);

raise 函数

#include <signal.h>
int raise(int sig);
  • 在 Linux 中,raise() 函数用于向当前进程发送一个信号
  • raise() 函数通过向当前进程发送一个指定的信号来触发信号处理函数的执行。
    • sig 参数指定了要发送的信号的编号,可以是任意有效的信号编号,如 SIGTERM、SIGINT 等。
  • 当调用 raise() 函数时,系统会向当前进程发送指定的信号,
    • 如果当前进程已经注册了对应信号的处理函数,那么该处理函数将会被执行。
    • 如果当前进程没有注册对应信号的处理函数,系统会根据默认的信号处理方式来处理这个信号,
    • 例如终止进程或者忽略信号等。

__SIGINFO

#define __SIGINFO struct { int si_signo; int si_errno; int si_code; union __sifields _sifields; 
}

解释

  1. int si_signo:信号的编号。
  2. int si_errno:如果信号与错误相关,则包含错误号。
  3. int si_code :标识信号的来源和类型。
  4. pid_t si_pid:发送信号的进程的 ID。
  5. uid_t si_uid:发送信号的用户的 ID。
  6. void *si_addr:与信号相关的地址。
  7. int si_status:进程的退出状态。
  8. clock_t si_utime:用户态运行时间。
  9. clock_t si_stime:系统态运行时间。
  10. sigval_t si_value:信号的附加数据。

Demo

#include <iostream>

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

using namespace std;

void handler(int signum, siginfo_t *siginfo, void *ucontext);

void init_sigaction(struct sigaction *act);

void handler(int signum, siginfo_t *siginfo, void *ucontext) {
    cout << __FUNCTION__ << endl;
    printf("handler called\n");
    printf("signum(SIGQUIT) is: %d\n", signum);
    printf("information in siginfo is:\n");
    printf("\tsi_signo:  %d\n", siginfo->si_signo);
    printf("\tsi_errno:  %d\n", siginfo->si_errno);
    printf("\tsi_code:   %d\n", siginfo->si_code);
    /* printf("\tsi_trapno: %d\n", siginfo->si_trapno); */
    printf("\tsi_pid:    %d\n", siginfo->si_pid);
    printf("\tsi_uid:    %d\n", siginfo->si_uid);
    printf("\tsi_status: %d\n", siginfo->si_status);
   // printf("\tsi_utime:  %ld\n", siginfo->si_utime);//
   // printf("\tsi_stime:  %ld\n", siginfo->si_stime);//
    printf("\tsi_value:  %d\n", siginfo->si_value );
    printf("handler exiting...\n");


}

void init_sigaction(struct sigaction *act) {
    cout << __FUNCTION__ << endl;
    act->__sigaction_u.__sa_sigaction = handler;
    sigemptyset(&act->sa_mask);
    act->sa_flags = SA_SIGINFO;
}

void testOne();

void testOne() {
    cout << __FUNCTION__ << endl;
    struct sigaction act;
    init_sigaction(&act);
    cout << "pid is : " << getpid() << endl;
    if (sigaction(SIGQUIT, &act, nullptr) == -1) {
        cerr << "sigaction error" << endl;
        exit(1);
    }
    raise(SIGQUIT);
    cout << "exiting..." << endl;
}


void ouch(int sig)
{
    printf("\nOUCH! - I got signal %d\n", sig);

    // 恢复终端中断信号SIGINT的默认行为
    (void) signal(SIGINT, SIG_DFL);
}

void testTwo();
void testTwo(){
    struct sigaction act;
    act.sa_handler = ouch;

    // 创建空的信号屏蔽字,即不屏蔽任何信息
    sigemptyset(&act.sa_mask);

    // 使sigaction函数重置为默认行为
    act.sa_flags = SA_RESETHAND;

    sigaction(SIGINT, &act, 0);

    while(1)
    {
        printf("Hello World!\n");
        sleep(1);
    }
}


int main() {
    // testOne();
    testTwo();
    return 0;
}

参考