注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

学习笔记

正确的方法如同学习书法,开始的时候要临摹,临摹好了然后创造自己的风格。

 
 
 

日志

 
 

[Linux笔记]Linux中的信号处理机制  

2012-04-22 09:02:48|  分类: Linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
嵌入式Linux系统实用开发——何永琪

1. 发送信号

       信号实际上是由一个正整数代表的,但为了方便使用,每个信号都定义了一个名称,代表了一种特殊的含义,这些信号定义在系统的头文件signal.h中。

1) kill

       像一个进程发送消息可以使用kill命令,默认情况下,kill命令发送SIGTERM信号以试图终止一个进程。如果要在程序中发送信号,则可以使用kill函数,其接口和原型如下:

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

       其中,pid参数用来指定信号发送的目标进程,有以下几种情况:

*      当pid>0时,sig发送给pid指定的进程。

*      当pid=0时,sig发送给调用进程所属组的每个进程。

*      当pid=-1时,sig发送给调用进程有权限发送信号的除进程1(init)之外的所有进程。

*      当pid<-1时,sig发送给进程组ID为-pid的所有进程。

       sig=0时,不发送任何信号,但是错误检查仍然执行。这可用来检测一个进程ID或进程组ID是否存在。

2)raise

       进程也可以给自己发送信号,但这种情况下,使用raise更方便,其接口头文件及原型如下:

#include <signal.h>

int raise(int sig);

等同于kill(getpid(), sig);

3)alarm

       可以在指定的时间之后向进程自己发送SIGALRM信号,其接口头文件及原型如下:

#include <unistd.h>

unsigned alarm(unsigned seconds);

       参数seconds表示一个以秒为单位的超时时间,超过这段时间之后,内核将自动向进程发送SIGALRM信号。如果在指定超时时间前再次调用alarm函数,则新的时间值将覆盖旧值,并且从当前时间开始重新计算。如果指定时间值为0,表示取消信号的发送。

2. 信号的捕捉

2.1 休眠函数介绍

1)pause()函数——等待信号

       使当前进程进入睡眠态,直到有信号发生。只有当信号被捕捉,并且信号捕捉函数返回时,它才返回-1,同时变量errno的值被设置为EINTR以表示有信号发生。其接口头文件及原型如下:

#include <unistd.h>

int pause(void);

2)sleep()函数——休眠指定的秒数

       使当前进程进入到休眠态,并在seconds参数指定的秒数后被唤醒继续执行。注意当有未忽略的信号发生时sleep函数会提前返回,返回值是剩下的秒数。如果返回0则说明是正常被唤醒的,而不是因为信号的发生提前返回的。

       

2.2 使用signal函数

       signal函数是Linux系统上的传统的信号处理接口,其接口头文件及原型如下:

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

       函数的作用是将handler参数所指向的函数注册成为参数signum所代表的信号处理函数,它的返回值是这个信号原来的处理函数,如果返回SIG_ERR,则说明有错误发生,注册失败。

       注册成功后,所注册的函数就会在信号被处理时调用,代替默认的行为,或者成为信号被捕捉。



2.3 使用sigaction函数

       signal函数的使用方法比较简单,但并不属于POSIX标准,在各类UNIX平台上的实现不尽相同,其用途受到了一定的限制。而POSIX标准定义的信号处理接口是sigation函数,其接口头文件及原型如下:

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

*      signum:要操作的信号。

*      act:要设置的对信号的新处理方式。

*      oldact:原来对信号的处理方式。

*      返回值:成功返回0;失败返回-1。

       signum指定的信号除SIGKILL和SIGSTOP之外都是有效信号。如果act非空,则信号signum将按照act执行新的动作。如果oldact非空,则就的动作被保存在oldact中。

struct sigaction {

    void     (*sa_handler)(int);

    void     (*sa_sigaction)(int, siginfo_t *, void *);

    sigset_t   sa_mask;

    int        sa_flags;

    void     (*sa_restorer)(void); //已废弃,不要使用。

};

       在这个结构体中,成员sa_handler是一个函数指针,指定了与signum匹配的动作,SIG_DFL表示默认动作,SIG_IGN表示忽略信号,或者是指向一个信号处理函数,该函数接受signum并作为其唯一的参数;

       成员sa_sigaction则是另外一个信号处理函数,它有三个参数,可以获得关于信号更详细的信息;

       当sa_flags成员的值包含SA_SIGINFO标志时,系统将使用sa_sigaction函数作为信号处理函数,并将信号值作为第一个参数,指向siginfo_t的指针作为第二个参数,空指针作为第三个参数(通常处理函数并不使用第三个参数);否则使用sa_handler作为信号处理函数。在某些系统中,成员sa_handler与sa_sigaction被放在联合体中,因此使用时不要同时设置。

       sa_mask成员用来指定在信号处理函数执行期间需要屏蔽(例如,添加到信号处理函数被调用的线程的信号掩码中)的信号,此外,触发handler的信号将阻塞,除非设置SA_NODEFER标志。

    sa_flags成员用于指定信号的处理行为,它可以是以下值的“按位或”组合。

*    SA_RESTART:是被信号打断的系统调用重新发起,只有在建立了信号处理函数时才有意义。

*    SA_NOCLDSTOP:如果signum是SIGCHLD,当子进程停止(比如:当接收到SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU之一)或者恢复(比如:当接收到SIGCONT),不会接受通知。只有为SIGCHLD建立了处理函数时才有意义。

*    SA_NOCLDWAIT:如果signum是SIGCHLD,当子进程终止时不会变为僵尸进程。

*    SA_RESETHAND:使信号处理之后重新设置为默认的处理方式。

*    SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发生这个信号。

*    SA_SIGINFO:使用sa_sigaction而不是sa_nandler作为信号的处理函数。
  评论这张
 
阅读(1085)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017