首页 > 其他分享 >信号的概念和机制

信号的概念和机制

时间:2024-03-26 22:11:06浏览次数:25  
标签:SIGRTMAX int 概念 屏蔽 信号 机制 sa SIGRTMIN

1.信号的概念和机制

理解信号可以参考生活中,烽火、狼烟等

信号的特点:1.简单;2.不能携带大量信息;3.满足某个特设条件才发送

1.1.信号的机制

信号时软件层面的“中断”信号VS中断VS异常,三个概念可以一起学习

每个进程收到的所有信号,都是由内核负责发送、内核处理的

简单地说,unix的信号机制,是一种软中断

1.2.与信号相关的概念

1.2.1.信号产生

  1. 按键,如:Ctrl + c、Ctrl + z、Ctrl + \
  2. 系统调用,如:kill raise abort
  3. 软件条件,如:定时器alarm
  4. 硬件异常,如:非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线错误)
  5. 命令产生,如:kill

1.2.2.信号的状态

image

  1. 信号产生/发送
  2. 未决
  3. 递达

1.2.3.信号的处理方式

  1. 执行默认工作(大部分信号时终止当前进程)
  2. 忽略(丢弃)
  3. 捕捉(执行用户处理函数)

1.3.信号屏蔽字与未决信号集

linux内核的进程控制块PCB是一个结构体,处理包含进程id、状态、工作目录、用户id、文件描述符表等,

还包括了信号相关的信息,主要是信号屏蔽字和未决信号集(本质是bitmap)

  • 信号屏蔽字(阻塞信号集):将某些信号加入集合,对他们设置屏蔽,当屏蔽x信号后,再收到x信号,x信号的处理将推后(解决屏蔽后)
  • 未决信号集:
    1. 信号产生,未决信号集中描述该信号的位立刻翻转为1,表示该信号处于未决状态。当信号被处理对应位翻转为0。这一时刻往往非常短暂
    2. 信号产生后由于某些原因(一般是阻塞)不能递达。这类信号的集合称为未决信号集。在屏蔽解除前,信号一直处于未决状态

image

1.4.信号四要素与常见信号

1.4.1.信号四要素

man 7 signal查看

  1. 编号

  2. 名称(不重要,代码开发中使用信号对应的宏)

  3. 事件(产生信号的事件)

  4. 默认处理动作

image

1.4.1.常见信号

linux终端输入:kill -l

  • 1-31信号:常规信号,有默认事件和处理动作

  • 34-64:实时信号,没有默认事件

 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

1.5.kill函数和kill命令

  • kill是发送一个信号给进程

man kill-->命令

man 2 kill-->函数

image

  • kill的第二个入参pid,传不同的值有不同的作用:

image

  • 一个例子
int main(int argc, char *argv[])
{
    pid_t pid = fork();

    if (pid > 0) {
        while (1) {
            printf("parent pid = %d\n", getpid());
            sleep(1);
        }

    } else if (pid == 0) {
        printf("******child pid = %d, ppid = %d\n", getpid(), getppid());
        sleep(2);
        printf("******child process will kill parent process = %d, ... ...\n", getppid());
        sleep(1);
        kill(getppid(), SIGKILL); // SIGKILL 默认动作:终止进程
        // kill(getppid(), SIGCHLD); // SIGCHLD 子进程状态发送变化给父进程发送该信号,默认进程:忽略该信号
    }

    return 0;
}
  • 其他发信号函数

    int raise(int sig);

    void abort(void);

1.6.两个闹钟(定时器)函数

1.6.1.alarm函数—自然定时

设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送14) SIGALRM信号。进程收到该信号,默认动作终止进程。

每个进程有且仅有一个定时器。

image

  • 常用:取消定时器alarm(0),返回定时器剩余秒数
int main(int argc, char *argv[])
{
    int cnt = 0;

    alarm(1); // 1秒后发送14) SIGALRM信号。进程收到该信号,默认动作终止进程

    while (1) {
        cnt++;
        printf("%d\n", cnt);
    }

    return 0;
}
  • 利用time指令执行程序:time a.out,发现:

    real > (user + sys),其中等待时间是由于printf调用write系统调用(进行标准输出),进行IO操作,比较耗时(程序运行的瓶颈在于IO)

real:程序实际运行时间

user:用户态时间

sys:内核态时间

image

  • 如果把IO到终端的打印重定向,time a.out > out,看看时间,1秒钟的计数:

image

1秒的计数值比之前大了很多很多:

image

1.6.2.setitimer

代替alarm,时间精度更高

image

1.7.信号集操作函数

1.7.1.set增删改查

自定义一个sigset_t类型的set(bitmap),信号集操作函数,对bitmap进行增删改查

image

1.7.2.sigprocmask函数——屏蔽信号、解除屏蔽

sigprocmask() is used to fetch and/or change the signal mask of the calling thread.

注意:屏蔽信号只是将信号处理延后执行(延至解除屏蔽);而忽略表示将信号丢弃处理

image

how的取值:

  • SIG_BLOCK:阻塞

  • SIG_UNBLOCK:解除阻塞

  • SIG_SETMASK:覆盖

1.7.3.sigpending函数——读取进程的未决信号集

image

1.7.4.信号集操作函数使用原理分析

自定义信号集set,去操作信号屏蔽字,进而影响未决信号集

  • set增删改查 函数—>sigprocmask 屏蔽或解除屏蔽

1.7.5.一个例子

void PrintSet(const sigset_t *set)
{
    int i;

    // 打印【1-32信号】
    for (i = 1; i < 32; i++) {
        if (sigismember(set, i)) {
            putchar('1');
        } else {
            putchar('0');
        }
    }
    printf("\n");
}

int main(int argc, char *argv[])
{
    sigset_t set, oldset, pedset;

    // 操作自定义的信号集set
    sigemptyset(&set);
    sigaddset(&set, SIGINT);

    // 用自定义set,操作pcb中的信号屏蔽字
    sigprocmask(SIG_BLOCK, &set, &oldset);

    while (1) {
        // 读取未决信号集:前面对信号屏蔽字的SIGINT信号设置了阻塞,当SIGINT信号产生时,未决信号集SIGINT信号bit会置1,且不会恢复为0,直至SIGINT信号解除
        // 其他信号同理,处理不能被阻塞/屏蔽的信号
        sigpending(&pedset);

        // 循环打印未决信号集
        PrintSet(&pedset);

        sleep(1);
    }

    return 0;
}

1.8.信号捕捉

1.8.1.signal函数

简单了解,非posix标准,使用sigaction替代

image

1.8.2.sigaction函数

image

  • 重点关注结构体sigaction
struct sigaction {
    void     (*sa_handler)(int);							// 捕捉到x信号对应的回调函数
    void     (*sa_sigaction)(int, siginfo_t *, void *);		// 信号携带结构体等复杂参数
    sigset_t   sa_mask;										// 重点:区别于pcb中的信号屏蔽字;这里的sa_mask只工作与信号捕捉函数执行期间
    int        sa_flags;
    void     (*sa_restorer)(void);
};
  • sa_mask
sa_mask specifies a mask of signals which should be blocked (i.e., added to the signal mask of the thread in which
the signal handler is invoked) during execution of the signal handler.  In addition, the  signal  which  triggered
the handler will be blocked, unless the SA_NODEFER flag is used.
    
翻译一下:
sa_mask指定在信号处理程序的执行期间应该被阻塞的信号的掩码(即,添加到调用信号处理程序所在线程的信号掩码)。此外,触发处理程序的信号将被阻止,除非使用SA_NODEFER标志。
  • 一个例子
void callback(int signum)
{
    if (signum == SIGINT) {
        printf("catch SIGINT signum=%d\n", signum);
    } else if (signum == SIGQUIT) {
        printf("catch SIGQUIT signum=%d\n", signum);
    }
}

int main(int argc, char *argv[])
{
    struct sigaction act, old;

    act.sa_handler = callback;      // 设置信号捕捉到的回调函数
    sigemptyset(&act.sa_mask);      // 初始化sa_mask,sa_mask只在信号回调函数执行期间生效,目的是为了防止回调函数死循环
    act.sa_flags = 0;               // 默认传0

    sigaction(SIGINT, &act, &old);  // 注册SIGINT信号的捕捉函数
    sigaction(SIGQUIT, &act, &old); // 注册SIGQUIT信号的捕捉函数

    while (1);

    return 0;
}

标签:SIGRTMAX,int,概念,屏蔽,信号,机制,sa,SIGRTMIN
From: https://www.cnblogs.com/kongweisi/p/18097741

相关文章

  • 深度学习批次(batch)、迭代(iteration)、周期(epoch)、前向传播(forward propagation)
    虽然现在应该是已经熟练掌握这些基础概念的时候,但是我是鱼的记忆,上一秒的事情,下一秒就忘了,除非是重要的人的重要的事情,呜呜呜呜,我这个破脑子.还是写一下吧,直接GPT出来的(人类之光,欢呼~).以前写过一次,贴一下链接:深度学习模型训练的过程理解(训练集、验证集、测试集、batch、itera......
  • Unix系统上使用semop函数写一个信号量函数,确保只有一个进程能访问临界资源
    semop是Unix系统调用,用于操作信号量集。信号量是一种用于保护共享资源或临界区域免受并发访问的同步原语。以下是一个使用semop的简单示例,确保只有一个进程能访问临界资源:#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<......
  • linux 线程的一些简答概念
    基本概念1.临界资源:多线程执行流共享的资源2.临界区:访问临界资源的代码3.原子性:只有完成和未完成两种状态。4.互斥:同一时间只能允许一个线程访问临界资源,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。可以加锁实现。加锁可以保证单个线程对临界......
  • 进程的概念介绍
    一、进程    进程是计算机中运行的程序的实例。每个进程都有自己的内存空间、代码、数据和系统资源。进程可以独立运行,相互之间不会影响。进程的基本概念包括:1.程序:进程是程序的一次执行,程序是存储在磁盘上的静态文件,而进程是程序在内存中的动态执行。2.状态:进程......
  • JAVA面向对象基本概念、类和对象
    基本概念一、什么是面向对象面向对象是一种编程思想面向对象是一种思考问题的思维方式二、建立面向对象的思维方式先整体,在局部;先抽象,在具体;能做什么,再做什么类和对象类是分类类别,通过分类可以区分不同事物种类类是具有一组相同特征(属性)与行为(方法)的事物集合类和对象的......
  • HFCG-3500+ 信号调节 LTCC High Pass Filter 3900-16500MHz 0805 陶瓷滤波器 Mini-Cir
    Mini-Circuits是一家专注于射频和微波产品的跨国公司,总部位于美国纽约。Mini-Circuits提供的产品涵盖了信号调理、信号发生、频率合成、混合信号处理等领域,广泛应用于无线通信、雷达、测试测量、航空航天等行业。制造商:   Mini-Circuits   产品种类:   信号调......
  • 二、kafka的文件存储机制
    简图: producer将数据写入kafka后,集群需要对数据进行保存。kafka将数据保存在磁盘,kafka初始会单独开辟一块磁盘空间,顺序写入(效率比随机写入高)。 1、partition结构partition在服务器上表现形式是一个个文件夹,生产者将生产的消息不断追加到log文件的末尾,为防止log文件过大......
  • 再聊SPI机制
    前言去年更新了一系列和SPI相关的内容,最近因为业务需要,我又基于业务场景,实现了一版。对于什么是spi,很久之前有写过一篇文章,java之spi机制简介感兴趣的朋友可以蛮看一下需求分析用过原生jdk提供的spi的朋友,应该会知道原生jdk的spi有个缺陷,就是没法实现按需加载,因此本文的实现就......
  • 【C语言学习日志】一点C语言概念
    学习目标:通读C语言的概念笔记内容:了解C语言C程序由函数所组成。所有C语言有且只有一个main()函数,并最先开始执行。 当main()函数结束时,程序也一同结束。 C语言功能1.数据表达数据类型,对具有共同特征的数据集合的总称。例如整型、实型(浮点型)、字符型【基本数据类型】。具......
  • MySQL中的MVCC实现机制
     MySQL中的MVCC实现机制   一、什么是MVCC?  MVCC,全称Multi-VersionConcurrencyControl,即多版本并发控制。MVCC是一种无锁的并发控制方法,一般在数据库管理系统中,用于实现对数据库的并发访问。  我们知道,在数据库中,对数据的操作主要有2中,分别是读和写,而在并发场景......