Linux学习笔记18——信号1

系统 1758 0

一 信号的基本概念

  信号:是向进程发送的软件通知,通知进程有事件发生。

  生成:表示一个信号的产生。

  捕获:表示接收到一个信号。

  信号的寿命:信号的生成和传递之间的时间间隔。

  挂起的信号:已经生成但还未被传递的信号。

二 产生信号

  每个信号名都是以SIG开头,信号的名字都定义在signal.h中,POSIX必需的信号如下:


 

  信号         描述 


  SIGABRT       进程放弃(signal abort)

  SIGALRM       告警时钟(signal alarm)

  SIGBUS       访问了内存对象中的为定义部分

  SIGCHLD       子进程被终止,停止或继续(signal child)

  SIGCONT       如果进程被停止了,本信号使进程继续执行(signal continue)

  SIGFPE       算术计算中出现了被零除这样的错误

  SIGHUP       在控制终端(进程)上挂起(死亡)

  SIGILL         无效的硬件指令

  SIGINT        交互终端提示信号(通常是Ctrl-C)

  SIGKILL       终止(signal kill)

  SIGPIPE       向一个没有读程序的管道写入(signal pipe)

  SIGQUIT       交互终端终止(通常是Ctrl-l)(signal quit)

  SIGSEGV        无效的内存引用

  SIGSTOP        执行停止(signal stop)

  SIGTERM       终止(signal terminate)

  SIGTTIN       后台进程试图进行读操作(signal try to input)

  SIGTTOU        后台进程试图进行写操作(signal try to output)

  SIGURG       在套接字上有高速宽数据

  SIGUSR1        用户定义的信号1

  SIGUSR2        用户定义的信号2


  1  函数kill

      #include <signal.h>




      
        int
      
       kill(pid_t pid,    
      
        //进程ID
      
      
int sig       //信号码
     );          //成功返回0,不成功返回-1并设置errno

  参数pid的取值:>0            kill就向那个ID表示的进程发送信号

           =0      kill就向调用程序的进程组成员发送信号

           -1       kill就向所有它有权发送信息的进程发送信号

          其它负值    就将信号发送到组ID等于|pid|的进程组中去  

  kill的实现必须检测的错误及相应的错误码:EINVAL:sig是一个无效的或不被支持的信号

                      EPERM:调用程序没有适当的权限

                      ESRCH:没有进程或进程组对应于pid

  例子:向进程1000发送SIGUSR1 

      
        if
      
      (kill(
      
        1000
      
      
        ,SIGUSR1)){



    perro(
      
      
        "
      
      
        Failed to send the SIGUSR1 signal
      
      
        "
      
      
        );



}
      
    

  注:查找相关进程ID的常用方法是使用getpid(获取当前进程ID),getppid(获取当前进程的父进程ID),getpgid(获取当前进程的进程组ID),或者通过保存从fork中返回的值来查找。

  2 函数raise

      #include <signal.h>




      
        int
      
       raise(
      
        int
      
       sig);  
      
        //成功,返回0,不成功如果sig是无效的,raise函数就将error设置为EINVAL
      
    

  raise函数用来向自己发送一个信号。

  例子:使进程向自己发送一个SIGUSR1信号

      
        if
      
      (raise(SIGUSR1)!=
      
        0
      
      
        ){



  perror(
      
      
        "
      
      
        Failed to raise SIGUSR1
      
      
        "
      
      
        );



}
      
    

  3 函数alarm

      #include <unistd.h>
      
        



unsigned alarm(unsigned seconds);
      
    

  alarm函数用来在seconds秒之后安排发送一个SIGALRM信号,alarm函数从来不报告错误。

 

三 对信号掩码和信号集的操作

  信号掩码:当前被阻塞的信号的集合,类型为sigset_t.

  对信号集的操作由以下五个函数组成:

      #include <signal.h>




      
        int
      
       sigaddset(sigset_t *
      
        set
      
      ,
      
        int
      
      
         signo);        
        
          //将signo加入信号集 
        
      
      
        int
      
       sigdelset(sigset_t *
      
        set
      
      ,
      
        int
      
      
         signo);        
        
          //将signo从信号集中删除 
        
      
      
        int
      
       sigemptyset(sigset_t *
      
        set
      
      
        );             
        
          //对信号集初始化,使其不包含任何信号 
        
      
      
        int
      
       sigfillset(sigset_t *
      
        set
      
      
        );             
        
          //对信号集初始化,使其包含所有信号 
        
      
      
        int
      
       sigismember(
      
        const
      
       sigset_t *
      
        set
      
      ,
      
        int
      
       signo);   
      
        //报告signo是否在*set中,如果在,返回1,否则返回0
      
    

  例子:对信号集twosigs进行初始化,使其包含两个信号SIGINT和SIGQUIT

      
        if
      
      ((sigemptyset(&twosigs)==-
      
        1
      
       || sigaddset(&twosigs,SIGINT)==-
      
        1
      
       || sigaddset(&twosigs,SIGQUIT)==-
      
        1
      
      
        )){



  perror(
      
      
        "
      
      
        Failed to set up signal mask
      
      
        "
      
      
        );



}
      
    

  进程可以用sigprocmask函数来检查或修改它的进程信号掩码,sigprocmask函数可以根据参数how指定的方法修改进程的信号掩码。新的信号掩码由参数set指定,而原先的信号掩码将保存到信号集oset中,声明如下:

      #include <signal.h>




      
        int
      
       signalprocmask(
      
        int
      
       how,
      
        
          //用来说明信号掩码的修改方式
        
        
           const
sigset_t *restrict set ,     //指向一个信号集的指针,在修改中要用到这个信号集,如果为NULL,就说明不需要进行修改
           sigset_t *restrict oset        //如果不为NULL,sigprocmask会将修改之前的信号集放在*oset中返回
           );

  参数how取以下三个值中的一个:

  SIG_BLOCK:向当前被阻塞的信号中添加一个信号集

  SIG_UNBLOCK:从当前被阻塞的信号中删除一个信号集

  SIG_SETMASK:将指定的信号集设置为被阻塞的信号

  例子:将SIGINT添加到进程已经阻塞的信号集中去

      
        sigset_t newsigset;




      
      
        if
      
      ((sigemptyset(&newsigset)==-
      
        1
      
       || sigaddset(&newsigset,SIGINT)==-
      
        1
      
      
        )){



  perror(
      
      
        "
      
      
        Failed to initialize the signal set
      
      
        "
      
      
        );



}




      
      
        else
      
      
        if
      
      (sigprocmask(SIG_BLOCK,&newsigset,NULL)==-
      
        1
      
      
        ){



  perror(
      
      
        "
      
      
        Failed to block SIGINT
      
      
        "
      
      
        );



}
      
    

 

Linux学习笔记18——信号1


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论