APUE——信号基础以及信号的响应

18 篇文章 0 订阅

1.信号基础

1.1 信号函数

#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);  这是可靠写法

void (* signal( int signo, void (*func)(int) )  )(int);

函数名      :signal

函数参数   :int signo, void (*func)(int)

返回值类型:void (*)(int);

信号的忽略: 信号忽略的核心是将mask中设置0,导致后续与操作始终是0,SIGKILL与SIGSTOP不能被忽略!另外,如果忽略某些由硬件异常产生的信号(例如除以0),则进程的运行行为是未定义的。
信号的默认动作:大多数的信号处理函数是终止进程!
信号捕捉:为了做到这一点,要通知内核在某种信号发生时调用一个用户函数。在用户函数中,可执行用户希望对这种事件进行的处理。注意,不能捕捉SIGKILL和SIGSTOP信号。
信号与中断:信号依赖于中断!
信号与系统调用:信号是可以打断系统调用的,所以在执行调用函数的时候,需要增加判断,errno是否是EINTR,如果是则continue,否则perror(“error”)

typedef void sigfun(int);
sigfun* signal(int signo, sigfun* func) //信号函数换一种写法
signo为信号no,func为信号处理函数
#define    SIG_ERR        ( void (*) () )-1
#define    SIG_DFL        ( void (*) () )0
#define    SIG_IGN        ( void (*) () )1

在这里插入图片描述
参考链接APUE

#include "apue.h"

static void sig_usr(int);    /* one handler for both signals */

int
main(void)
{
    if(signal(SIGUSR1, sig_usr) == SIG_ERR)
        err_sys("can't catch SIGUSR1");
    if(signal(SIGUSR2, sig_usr) == SIG_ERR)
        err_sys("can't catch SIGUSR2");
    for(;;)
        pause();
}

static void sig_usr(int signo)    /* argument is signal number */
{
    if(signo == SIGUSR1)
        printf("received SIGUSR1\n");
    else if (signo == SIGUSR2)
        printf("received SIGUSR2\n");
    else
        err_dump("received signal %d\n", signo);
}

可以用signal(1), signal -SIGUSR1 pidno来查看结果

1.2 信号产生

产生信号的条件:

  1. 当用户按某些终端键时,引发终端产生的信号。
  2. 硬件异常产生信号。
  3. 进程调用kill(2)函数可将信号发送给另一个进程或进程组。(自然,对此有所限制:接收信号进程和发送信号进程的所有者必须相同,或者发送信号进程的所有者必须是超级用户。)
  4. 用户可用kill(1)命令将信号发送给其他进程。
  5. 当检测到某种软件条件已经发生,并应将其通知有关进程时也产生信号。(这里指的不是硬件产生的条件,而是软件条件。)
    在信号产生(generation)和递送(delivery)之间的时间间隔,称信号是未决的(pending)

1.3可重入函数

信号的函数执行是可以被打断的,所以会涉及到函数的可重入,系统调用函数都是可重入的,后续在sigaction里可以设置信号处理函数会自动重启被打断的系统调用,一部分库函数也是可重入的
可冲重入的函数列表如下:在这里插入图片描述
(a)已知它们使用静态数据结构,(b)它们调用malloc或free,或(c)它们是标准I/O函数。

1.4 实时信号与非实时信号

在这里插入图片描述
其中1-31 是非实时信号,是不可靠信号, 34-64是实时信号,是可靠的
非实时信号是通过pending位图来实现,同时出现多个信号会覆盖
实时信号是有队列的,可以ulimit -a来查看pending最大个数,同时出现多个信号会排队

2. 信号响应策略

信号响应的过程

  1. 信号从接收到响应是有一个延迟的,因为需要等待中断
  2. 标准信号是没有严格的响应顺序的
  3. 因为pending位图的关系,导致如果连续多个标准信号到来,pending会被覆盖,所以会出现丢失,没有队列!

注意点:

  1. 进程中的信号位图的初始时刻pending均为0,mask均为1,后续可以通过sigprocmask,sigaction等来修改,阻塞信号mask置0。应结合SA_NODEFER分析。
  2. 信号在用户态切换到内核态前要进行位与操作,判断是否有信号
  3. 只有当有中断到来后,当前进程进入内核态,信号本身到来并不能立刻响应
  4. 进程在内核态发现信号后,将mask与pending均置0,当信号处理函数执行完后,会将mask置1,pending置0!
    在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值