linux笔记之初次接触信号

一.关于信号概念


1.信号是Linux所使用的进程间通信的最古老的方式。它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。一个完整的信号周期包括三个部分,信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数。如下图所示:这里写图片描述

这里的对信号产生注册和注销都是信号的内部机制,而不是信号函数完成的

2.对信号的处理动作有三种:

a. 忽略此信号

b.执行该信号的默认处理动作

c.捕捉信号(自由态)

3.查看系统定义中的信号列表: kill -l 命令

这里写图片描述
每个信号都有一个编号和一个宏定义名称,这些宏定义名称可以在signal.h中找到,例如:其中有定义#define SIGINT 2

二.产生信号

1. 通过终端按键产生信号

如下代码:

#include<stdio.h>
#include<signal.h>
void hander(int sig)
{
    printf("%d\n",sig);
}


int main()
{
    signal(2,hander);
    while(1)
    {
        printf("i am a proc\n");
        sleep(1);
    }
}

这里写图片描述
以上代码使用了signal函数用来捕捉信号,则可以说明的是:ctrl+c实现的是信号的2号信号SIGINT。

2.调用系统函数向进程发信号

介绍几个函数

  • kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号。
#include<signal.h>
int kill(pid_t pid,int signo);
  • raise函数可以给当前进程发送指定的信号(自己给自己发信号)
#include<signal.h>
int raise(int signo);

如下两个代码实现raise函数的功能:

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>

void hander(int sig)
{
    printf("%d\n",sig);
}

int main()
{
     signal(2,hander);
     sleep(3);
     while(1)
     {
       raise(2);
        printf("i am a proc\n");
        sleep(1);
    }

}

结果如下图:

这里写图片描述

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>

void hander(int sig)
{
    printf("%d\n",sig);
}

int main()
{
     signal(2,hander);
     sleep(3);
     raise(2);
     while(1)
     {
        printf("i am a proc\n");
        sleep(1);
    }

}

结果如下图:

这里写图片描述

  • abort函数可以使当前进程接收到信号而异常终止,像exit函数一样,abort函数总会成功,故无返回值
#include<stdlib.h>
void abort(void);

3.由软件条件产生信号

例如:模拟闹钟

调用alarm函数可以设定一个闹钟,告诉内核在seconds秒之后给当前进程发SIGALRM信号,该信号的默认动作是终止当前程序

该函数的返回值是0或者是以前设定的闹钟时间还余下的秒数

用以下代码实现alarm的功能:

代码1:

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

int main()
{
    alarm(1);
    int count=0;
    for(;1;count++)
    {
    printf("count= %d\n",count);
    }
    return 0;
}

结果示意图:

这里写图片描述

###代码2:

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>

int count=0;

void hander(int sig)
{
    printf("count = %d\n",count);
}


int main()
{
    signal(14 ,hander);
    alarm(1);
    while(1)
    {
        count++;
    }

    return 0;

结果示意图:

这里写图片描述

以上两个代码均是表示count 在1 秒累加的次数,从结果看出第二个数比第一个数大很多,所以说明输入输出流对计算的速度影响非常大

三.阻塞信号


1. 信号在内核中的表示

a.实际执行信号的处理动作叫信号递达(Delivery),信号从产生到递达的状态,称为信号未决(Pending).进程可以选择阻塞某个信号。

b.信号阻塞就不会被递达,除非信号先被未决,然后解除阻塞。

c.信号在那内核中的表示示意图:

这里写图片描述

2.信号集操作函数

#include<signal.h>
int sigemptyset(sigset_t *set);//初始化set所指向的信号集,使其所有的bit清零,表示该信号集不包含任何有效信号。
int sigfillset(sigset_t *set);//初始化set所指向的信号集
int sigaddset(sigset_t *set,int signo);//在信号集中添加某种信号
int sigdelset(sigset_t *set,int signo);//在信号集中删除某种信号
int sigismemset(const sigset_t *set,int signo);//是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,包含返回1,反之返回0;

3.sigprocmask

#include<signal.h>
int sigprocmask(int how,const sigset *set,sigset_t *oset);//可以读取和改进进程的信号屏蔽字(阻塞信号集)

4.sigpending

#include<signal.h>
int sigpending(sigset_t *set);//读取当前进程的未决信号集,通过set参数传出

使用以上函数模拟一个信号在内核中的表示

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void show(sigset_t* pending)
{
    int i=1;
    for(; i<32; i++)
    {
        if(sigismember(pending,i))
        {
            printf("1 ");
        }
        else
        {
            printf("0 ");
        }
    }
    printf("\n");
}


int main()
{
    sigset_t block;
    sigset_t oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigfillset(&block);
    sigfillset(&oblock);
    sigaddset(&block,2);
    sigprocmask(SIG_BLOCK,&block,&oblock);
    sigprocmask(SIG_BLOCK,&oblock,NULL);

    while(1)
    {
        sigpending(&block);

        show(&block);
        sleep(1);
    }
    return 0;

}

结果示意图:

这里写图片描述

程序运行时候,每秒钟都把各个信号的未决状态打印一遍,由于我们阻塞了SIGINT信号,故按CTRL+C将会使SIGINT信号处于未决状态,按CTRL+\则可以终止程序,因为SIGQUIT信号没有被阻塞。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值