Linux中信号-学习笔记(五)

一、概念:
信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等。

1、分类:分为软中断和硬中断产生的信号,其中软中断实际为借助硬件手段完成。
2、特点
   1)简单;2)不能携带大量信息;3)满足某个条件才发送。
3、特质
   由于信号通过软件方法实现,具有很强延时性对用户来讲,时间非常短,不易察觉。
4、每个进程收到的所有信号,都由内核负责发送,由内核处理。

二、与信号相关的事件或名词
1、产生信号的基本方法
  1)系统调用当前进程的执行函数(kill)
  2)通过命令产生 kill
  3)硬件异常,段错误:内存出错;总线出错。
  4)软件条件产生(alarm,定时器) 
  5)按键测试的(ctrl+c)

三、信号的处理方法
1、默认动作 例如:ctrl+c将进程杀死
   如:终止进程、终止进程并且产生core文件(用于调试)、忽略、暂停、继续等
2、忽略(丢弃) 信号处理完,把信号丢弃,不在未决集里
3、信号捕捉 ,不去执行默认动作
//程序1 执行程序杀死当前进程
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

//man 2 kill  查看头文件

int main()
{
    int ret;
    ret=kill(getpid(),SIGKILL);//把参数SIGKILL信号发送给当前进程。
    if(ret==-1)//调用失败
    {
        exit(1);
    }
    return 0;
}
程序执行效果:

//程序2 创建5个子进程,杀死其中第三个子进程
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define N 5

int main()
{
    int i;//普通变量
    pid_t pid,q;//进程返回值
    for(i=0;i<N;i++)
    {
        pid=fork();//创建进程
        if(pid==0)//子进程
        {
            break;
        }
        if(i==2)
        {
            q=pid;
        }
    }
    if(i<N)
    {
        while(1)
        {
            printf("I am the child %d,pid=%d\n",i,getpid());
            sleep(1);
        }
    }
    else
    {
        kill(q,SIGKILL);//杀死第q个进程
    }
    return 0;
}
四、定时器
1、每个进程只有唯一一个定时器。
2、无论进程处于何种状态(运行,就绪,僵尸,终止)下,都在计时
3、功能:设置一个闹钟,发送alarm信号
4、返回值:返回之前剩余的信号。
5、time 命令:用于查看程序执行时间,实际时间=系统时间+用户时间+等待时间
6、setitimer  周期性定时,微秒
  1)计算自然时间14
  2)只计算进程占用CPU的时间 25
  3)计算占用CPU及系统调用的时间26
结构体struct itimerval,成员:
  1)it_value:设定触发时间。
  2)it_interval:设定触发周期。
1)、2)均有(int)tv_sec,(int)tv_usec的结构体成员。

补充:
进程A产生信号,通过内核马上送到进程B
阻塞信号集:即信号屏蔽字
未决信号集:没有被处理掉的信号集合
kill -l   //查看当前所有的信号
//程序3-1  计算计算机1s能数多少个数(法一)
#include <unistd.h>
#include <stdio.h>
//time ./count1   --显示具体执行时间
int main(void)
{
    int i;
    alarm(1);//定时1s
    for(i=0;;i++)
    {
        printf("%d\n",i);//显示数字
    }
    return 0;
}

//程序3-2 计算计算机1s能数多少个数(法二)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

//定时函数定义
unsigned int myalarm(unsigned int sec)
{
    struct itimerval it,oldit;
    int ret;
    it.it_value.tv_sec=sec;//设定触发时间
    it.it_value.tv_usec=0;
    
    it.it_interval.tv_sec=sec;//设定触发周期
    it.it_interval.tv_usec=0;
    
    ret=setitimer(ITIMER_REAL,&it,&oldit);//定时
    if(ret==-1)
    {
        exit(1);
    }
    return oldit.it_value.tv_sec;
}
//主函数
int main(void)
{
    int i;
    myalarm(1);//调用定时函数
    for(i=0;;i++)
    {
        printf("%d\n",i);//输出数字
    }
    return 0;
}

程序执行效果:

//程序4 将捕捉到的信号用定时方式输出
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>

void myfun(int signo)//输出hello world
{
    printf("hello world\n");
}

void myfun2(int signo)
{
    printf("close error\n");
}

int main(void)
{
    struct itimerval it,oldit;//定义结构体类型变量
    //捕捉的信号
    signal(SIGALRM,myfun);
    //屏蔽ctrl+c
    //signal(SIGINT,myfun2);
    
    int ret;
    it.it_value.tv_sec=5;//5s触发一次
    it.it_value.tv_usec=0;
    
    it.it_interval.tv_sec=3;//3s的间隔
    it.it_interval.tv_usec=0;
    
    ret=setitimer(ITIMER_REAL,&it,&oldit);//设置定时
    if(ret==-1)
    {
        printf("settimer error");
        exit(1);
    }
    for(;;);//让程序持续执行
    return 0;
}

程序执行效果:

//程序5 输出当前进程未决信号集,及测试屏蔽信号
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

//显示函数定义
void printfped(sigset_t *ped)
{
    int i;
    for(i=0;i<32;i++)
    {
        if(sigismember(ped, i)==1)//判断信号是否存在信号集中,'1'为存在
        {
            putchar('1');//输出1
        }
        else
        {
            putchar('0');//输出0
        }
    }
    printf("\n");
    sleep(1);
}
//主函数
int main(void)
{
    //自定义集合,影响pcb,阻塞信号集
    sigset_t myset,oldset,ped_set;    
    sigemptyset(&myset);//清空自定义信号集
    //sigaddset(&myset,SIGQUIT);//设置ctrl+/信号(3)
    sigaddset(&myset,SIGINT);//设置ctrl+c信号(2)
    sigaddset(&myset,SIGTSTP);//设置ctrl+z信号(19)   
    sigprocmask(SIG_BLOCK,&myset, &oldset);//读取或更改进程的信号屏蔽字  
    //查看未决信号集
    while(1)
    {
        sigpending(&ped_set);    
        //显示
        printfped(&ped_set);
    }
    return 0;
}
程序执行效果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值