Signal mask and pending signals
       A signal may be blocked, which means that it will not be
       delivered until it is later unblocked.  Between the time when it
       is generated and when it is delivered a signal is said to be
       pending.
https://man7.org/linux/man-pages/man7/signal.7.html

根据文档,信号可以是blocked 或者unblocked,信号可以仅面向进程和仅面向线程

blocked 信号

针对blocked 的信号 不会交由进程处理知道这个信号unblocked。pending 是信号产生然后交由进程处理的状态。

unblocked信号

将会交由信号处理函数处理,操作系统判断当前是否有挂起(pending)的非阻塞(unblocked)信号.

  1. 内核做些准备工作:
    1. 从挂起的信号集合中移除。
    2. 在sigaction 指定SA_ONSTACK 标志,则准备栈。
    3. 保存信号相关上下文。
    4. 配置sigprocmask设置的信号掩码,被处理的心有也会加入信号掩码除非设置SA_NODEFER。这些信号在信号处理器执行期间都是阻塞状态。
  2. 内核给信号处理函数分配一段栈,将pc指向函数头,配置好返回地址。
  3. 内核将控制流还给用户态的信号处理函数
  4. 当信号处理函数返回时,跳转到信号跳板(trampoline)函数。
  5. 信号跳板函数调用sigreturn。还原信号掩码,回到用户态,被线程处理函数中断的线程重新开始运行。
//
// Created by pareto on 11/24/22.
//
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#include<pthread.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int flag = 0;
void handler(int sig)
{
    puts("Hello WOrld\n");
    if (sig == SIGINT){
        printf("recv a sig=%d\n", sig);
        fflush(0);
    }

    else if (sig == SIGQUIT)
    {
        printf("rev a sig=%d\n", sig);
        sigset_t uset;
        sigemptyset(&uset);
        sigaddset(&uset, SIGINT);
        sigprocmask(SIG_UNBLOCK, &uset, NULL);
        flag = 1;
    }

    sleep(1000000000);

}

void printsigset(sigset_t *set)
{
    int i;
    for (i = 1; i < NSIG; i++)
    {
        if (sigismember(set, i))
            putchar('1');
        else
            putchar('0');
    }
    printf("\n");
}

void* anotherThread(void* args) {

    if (signal(SIGINT, handler) == SIG_ERR)
        ERR_EXIT("signal error");

    sleep(1000000000);
    return NULL;
}

int main(int argc, char *argv[])
{
    if (signal(SIGINT, handler) == SIG_ERR)
        ERR_EXIT("signal error");
    if (signal(SIGQUIT, handler) == SIG_ERR)
        ERR_EXIT("signal error");

    sigset_t pset; // 64bit
    sigset_t bset;
    sigemptyset(&bset);
    sigaddset(&bset, SIGINT);
//    sigaddset(&bset, SIGQUIT);
    //sigprocmask(SIG_BLOCK, &bset, NULL);

    pthread_t tid;
    pthread_create(&tid, NULL, &anotherThread, NULL);

    sleep(1000000000);
    printf("exit\n");
    exit(0);

    for (; ;)
    {
        sigpending(&pset); //return the set of signal thar are pending for delivery
        printsigset(&pset);//print all pending signal
        sleep(1);
//        if (flag == 1)
//            sigprocmask(SIG_UNBLOCK, &bset, NULL);
    }

    return 0;
}


pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注