• 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(" ");
    //又一次启动定时器,实现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 ",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);
    }
    }
    }
  • 相关阅读:
    『深度应用』NLP机器翻译深度学习实战课程·零(基础概念)
    Sorl初始
    Hadoop简介
    lucene的分词器宝典
    Lucene 更新、删除、分页操作以及IndexWriter优化
    Lucene 初步 之 HelloWorld
    lucene介绍和存储介绍
    Spring 集成rabbiatmq
    RabbitMQ 之消息确认机制(事务+Confirm)
    RabbitMQ 的路由模式 Topic模式
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6782474.html
Copyright © 2020-2023  润新知