【linux 信号】学习笔记

一. 几个时刻点:

1.信号诞生;

2.信号在进程中注册完毕;

3.信号在进程中的注销完毕;


(信号加入进程屏蔽字block中,函数执行完毕返回时,block恢复为原来的值)

(不管是否屏蔽信号,注销是肯定的)


4.信号处理函数开始执行。


(sa_flags不为SA_NOMASK/SA_NODIFFER,该信号在此过程被屏蔽;否则不被屏蔽,可以执行。)


5.信号处理函数执行完毕。相邻两个事件的时间间隔构成信号生命周期的一个阶段。


二. 安装信号用signal和sigaction函数

       signal用于安装不可靠信号

       sigaction可以安装可靠和不可靠信号

      1. 函数:int sigaction(ing signum, const struct sigaction *act, struct struct sigaction *oldact);中

           函数执行成功返回0,执行失败返回-1,错误码仿如errno中。

           signum是信号编号;

           act和oldact都是sigaction类型的结构体


        2.sigaction类型结构体

        struct sigaction

        {

               void (*sa_handler)(int);            处理函数

               void (*sa_sigaction)(int, siginfo_t *, void *);        处理函数(二者选其一)(第二个参数为结构体指针,指定要传送给函数数据,第一个为信号编号,第三个一般为NULL)

               sigset_t  sa_mask; 屏蔽字,指定block中要屏蔽的信号,缺省为当前处理的信号(sa_flags不指定为SA_NOMASK)

               int sa_flags; 标志字。

               void  (*sa_restorer)(void);        现在已经不用了

       }


       sa_flags设置为SA_SIGINFO,则使用第二个处理函数。

        struct siginfo

        {

                所有信号都有这三个数据成员

                int  si_signo;信号编号

               int  si_errno;错误码

                int  si_code;信号产生的原因

                ...

       }


三. 看以下程序:

#include<stdio.h>
#include<setjmp.h>
#include<signal.h>
#include<unistd.h>

#define ENV_UNSAVE 0
#define ENV_SAVED  1

int flag_saveenv=ENV_UNSAVE;
jmp_buf env;

void handler_sigrtmin15(int signo)
{
    if(flag_saveenv==ENV_UNSAVE)
        return;
    printf("recv SIGRTMIN+15\n");
    sleep(5);
    printf("in handler_sigrtmin15,after sleep\n");
    siglongjmp(env,1);
}

int main()
{
//    sleep(5);
    switch(sigsetjmp(env,1))
    {
    case 0:
        printf("return 0\n");
//        flag_saveenv=ENV_SAVED;
        break;
    case 1:
        printf("return from SIGRTMIN+15\n");
        break;
    default:
        printf("return else\n");
        break;
    }
    signal(SIGINT,handler_sigrtmin15);
    
    printf("gotowhile\n");
    while(1)
    ;    
    return 0;
}

信号处理函数中return到了while循环里,而不是signal函数中。


以下程序也是这样:

#include<stdio.h>
#include<unistd.h>
#include<signal.h>

int temp=0;

void handler_sigint(int signo)
{
    printf("\nrecv SIGINT\n");
    sleep(4);
    temp+=1;
    printf("the value of temp is %d\n",temp);
    printf("in handler_sight,after sleep\n");
}

int main()
{
    struct sigaction act;
    
    act.sa_handler=handler_sigint;
    act.sa_flags=SA_NOMASK;
    sigaction(SIGINT,&act,NULL);
    
    while(1)
    ;

    return 0;
}


在信号处理函数的sleep期间第二次按下ctrl C,响应完成后返回到sleep函数处,然后立刻执行下面的语句,不再sleep。而不是返回到sigaction函数处。因此,signal和sigaction只是安装了响应函数,而不是调用。可以认为是在信号发生处调用了信号处理函数,如果运行完或return,就返回到信号发生处。


四. 为给SIGINT安装响应函数时,按ctrl C默认的是终止进程;如果安装后,就按照响应函数去执行。


五. 信号处理函数执行到siglongjmp(env,1)时,siglongjmp先去除当前的信号屏蔽字,然后准备返回,但是若是去除当前屏蔽字之后,未决信号队列仍然有信号,那么返回前,先响应信号。

     信号响应函数执行完时,block才会回复原来值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值