0%

Linux多线程信号处理

信号等待sigwait函数

  • sigwait函数用于等待特定的信号以备处理
    #include <signal.h>

    int sigwait(const sigset_t *set, int *sig);
  • 在Linux系统中,一般来讲一个多线程的程序收到信号的时候,信号会被发送给主线程(main函数所在的线程),如果主线程不具备处理某个信号的能力而且也没有屏蔽该信号的话,进程会被直接终止。然而,这并不是绝对的规则,因为信号的传递行为受到操作系统的影响。
  • 当一个进程的一组线程中只有一个线程具备sigwait的时候,信号会被传递给这个线程
  • 注意,假如准备使用sigwait处理信号,则不能同时使用signal()注册信号,因为使用signal注册的信号处理函数会在线程遇到信号的时候直接异步执行,执行的进程号是main函数所在的主线程
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <sched.h>
    #include <signal.h>
    #include <unistd.h>

    #define THREADS 11

    // 信号处理函数
    void signal_handler(int signal_num) {
    if (signal_num == SIGUSR1) {
    printf("Received SIGUSR1 at process: %d , thread: %lu\n", getpid(), pthread_self());
    }
    }

    void *worker(void *arg) {
    struct sched_param param;
    int policy = SCHED_FIFO;

    param.sched_priority = 50;


    if (pthread_setschedparam(pthread_self(), policy, &param)) {
    perror("pthread_setschedparam");
    exit(EXIT_FAILURE);
    }
    if(arg != NULL)
    {
    printf("signal handler thread %lu\n", pthread_self());
    // 定义一个信号集
    sigset_t set;
    int signal_num;
    // 初始化信号集,添加需要处理的信号
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    // signal(SIGUSR1, signal_handler);
    while (1) {
    // 这里是你的工作代码
    sigwait(&set, &signal_num);
    printf("Received signal %d at thread %lu\n", signal_num, pthread_self());
    // sched_yield();
    }
    }
    else
    {
    printf("thread %lu\n", pthread_self());
    while (1)
    {
    sleep(1);
    }

    }

    return NULL;
    }

    int main() {
    pthread_t tid[THREADS];
    int i;

    pid_t pid = getpid();
    printf("pid: %d\n", pid);
    // 屏蔽主线程中的SIGUSR1信号,以便在信号处理线程中处理
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    pthread_sigmask(SIG_BLOCK, &set, NULL);
    // signal(SIGUSR1, signal_handler);
    printf("Main thread %lu\n", pthread_self());
    for (i = 0; i < THREADS; i++) {
    if (pthread_create(&tid[i], NULL, worker, NULL)) {
    perror("pthread_create");
    exit(EXIT_FAILURE);
    }
    }
    int f = 1;
    pthread_t sighandler;
    pthread_create(&sighandler, NULL, worker, &f);

    for (i = 0; i < THREADS; i++) {
    if (pthread_join(tid[i], NULL)) {
    perror("pthread_join");
    exit(EXIT_FAILURE);
    }
    }
    pthread_join(sighandler, NULL);

    return 0;
    }
  • picture 0