【无标题】linux中的两个很重要的信号:SIGALRM信号和SIGCHID信号

linux中的两个很重要的信号:SIGALRM信号和SIGCHID信号

在进行堵塞式系统调用时。为避免进程陷入无限期的等待,能够为这些堵塞式系统调用设置定时器。Linux提供了alarm系统调用和SIGALRM信号实现这个功能。

要使用定时器。首先要安装SIGALRM信号。假设不安装SIGALRM信号,则进程收到SIGALRM信号后。缺省的动作就是终止当前进程。

SIGALRM信号成功安装后,在什么情况下进程会收到该信号呢?这就要依赖于Linux提供的定时器功能。在Linux系统下,每一个进程都有惟一的一个定时器,该定时器提供了以秒为单位的定时功能。在定时器设置的超时时间到达后,调用alarm的进程将收到SIGALRM信号。

alarm系统调用的原型为:

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

參数说明:

1)seconds:要设定的定时时间,以秒为单位。在alarm调用成功后開始计时。超过该时间将触发SIGALRM信号。

返回值:

返回当前进程曾经设置的定时器剩余秒数。

例8-10:编程利用SIGALRM信号实现秒定时器。

代码例如以下:

#include <stdio.h>

#include <signal.h>

//全局计数器变量

int Cnt=0;

//SIGALRM信号处理函数

void CbSigAlrm(int signo)

{

        //输出定时提示信息

        printf("   seconds: %d",++Cnt);

        printf("\r");

        //又一次启动定时器,实现1秒定时

        alarm(1);

}

void main()

{

        //安装SIGALRM信号

        if(signal(SIGALRM,CbSigAlrm)==SIG_ERR)

        {

        perror("signal");

        return;

        }

        //关闭标准输出的行缓存模式

        setbuf(stdout,NULL);

        //启动定时器

        alarm(1);

        //进程进入无限循环,仅仅能手动终止

        while(1)

        {

                / /暂停,等待信号

                pause();

        }

}

8.5.2 SIGCLD信号

        在Linux的多进程编程中,SIGCLD是一个很重要的信号。当一个子进程退出时。并非马上释放其占用的资源,而是通知其父进程,由父进程进行兴许的工作。

在这一过程中,系统将依次产生下列事件。

1)向父进程发送SIGCLD信号,子进程进入zombie(僵尸)状态。

2)父进程接收到SIGCLD信号,进行处理。

        假设在上述过程中父进程既没有忽略SIGCLD信号。也未捕获该信号进行处理,则子进程将进入僵尸状态。僵尸状态的进程不能被操作系统调用,也没有不论什么可执行代码,它只是是占用了进程列表中的一个位置而已。

假设仅有几个僵尸进程不会影响系统的执行,可是假设僵尸进程过多。则将会严重影响系统的执行。因此,在编程过程中应避免产生僵尸进程。有两种主要的处理方法能够避免产生僵尸进程:一是父进程忽略SIGCLD信号;二是父进程捕获SIGCLD信号,在信号处理函数中获取子进程的退出状态。忽略信号的方式比較简单。仅仅须要调用signal(SIGCLD,SIG_IGN)语句就可以完毕。假设要捕获信号并处理。那么先要安装SIGCLD信号,然后在信号处理函数中调用wait或者waitpid等函数获取子进程的退出状态。

例8-11:编程捕获SIGCLD信号。输出各子进程的ID和退出状态码。

代码例如以下:

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

//SIGCLD信号处理函数

void CbSigCld(int signo)

{

        //保存退出进程的ID

        int pid;

        //保存退出进程的退出状态码

        int status;

        //等待不论什么一个子进程退出

        pid=waitpid(-1,&status,0);

        //输出退出的子进程ID和退出代码

        printf("Child process %d exit with status %d\n",pid,status);

}

void main()

{

        int i,pid;

        //安装SIGCLD信号

        if(signal(SIGCLD,CbSigCld)==SIG_ERR)

        {

                perror("signal");

                return;

        }

        //循环创建子进程

        for(i=0;i<5;i++)

        {

                pid=fork();

                //假设是子进程

                if(pid==0)

                {

                        //退出子进程,退出状态码为0

                        exit(0);

                }

        //假设是父进程

        else

        {

        sleep(1);

        }

        }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值