现在的位置: 首页 > 综合 > 正文

[APUE]第十章 信号

2012年12月16日 ⁄ 综合 ⁄ 共 3793字 ⁄ 字号 评论关闭

信号概念

不存在编号为0的信号。

产生信号的方式:

1          当用户按某些终端键时,引发终端产生信号。

2          硬件异常产生信号,比如SIGSEGV信号。

3          进程调用kill函数可将信号发送给另外一个进程或者进程组。

4          当检测到某种条件发生时,并应将其通知有关进程时也产生信号。比如SIGPIPE信号。

应用程序对产生的信号有三种方式进行处理

1          忽略信号

2          系统默认

3          安装信号处理函数,让信号处理函数来处理

 

kill –l 可以查看系统中的信号编号

ubuntu 信号集

root@LeoK:~/APUE/8_test# kill -l
 1)SIGHUP      2) SIGINT        3) SIGQUIT     4) SIGILL         5)SIGTRAP
 6)SIGABRT    7) SIGBUS       8) SIGFPE        9) SIGKILL       10)SIGUSR1
11) SIGSEGV     12)SIGUSR2     13) SIGPIPE      14) SIGALRM   15) SIGTERM
16) SIGSTKFLT  17) SIGCHLD    18) SIGCONT    19) SIGSTOP     20)SIGTSTP
21) SIGTTIN      22)SIGTTOU    23) SIGURG      24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM        27) SIGPROF     28)SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS        34)SIGRTMIN 35) SIGRTMIN+1      36) SIGRTMIN+2      37) SIGRTMIN+3
38) SIGRTMIN+4      39) SIGRTMIN+5      40)SIGRTMIN+6      41) SIGRTMIN+7      42) SIGRTMIN+8
43) SIGRTMIN+9      44) SIGRTMIN+10    45)SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50)SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55)SIGRTMAX-9      56) SIGRTMAX-8      57) SIGRTMAX-7
58) SIGRTMAX-6      59) SIGRTMAX-5      60)SIGRTMAX-4      61) SIGRTMAX-3      62) SIGRTMAX-2
63) SIGRTMAX-1      64) SIGRTMAX

下列情况是不产生core为

1进程是设置用户ID的,而且当前用户并非程序文件的所有者

2进程是设置了组ID的,而且当前用户并非程序文件的所有者

3用户没有写当前用户的权限

4该文件太大

 

SIGPIPE信号生成

tips:

调用execl 子进程的信号处理函数都会被冲掉,使信号处理函数变成默认行为。

当一个进程调用fork的时候,其子进程继承父进程的信号处理方式

 

 

signal信号安装函数

typedef void sig_dispose(int sig_no);
sig_dispose signal(sig_dispose func1);

其中函数地址可以指定如下宏

#ifndef __ASSEMBLY__
typedef void __signalfn_t(int);
typedef __signalfn_t *__sighandler_t;
typedef void __restorefn_t(void);
typedef __restorefn_t *__sigrestore_t;
#define SIG_DFL      ((__sighandler_t)0) /* default signal handling */
#define SIG_IGN      ((__sighandler_t)1) /* ignore signal */
#define SIG_ERR      ((__sighandler_t)-1)         /* error return from signal */
#endif

不可靠信号(博客中有一篇主要讲可靠信号和不可靠信号之间的区别)

 

中断系统调用:

对于正在执行低速系统调用的时候,收到信号,那么进程就会捕捉到这个信号,中断这个低速的系统调用,并且把errno设置为EINTR表示被信号中断了。

可重入函数

不可重入函数的原因是api内部使用了全局静态数据结构,每一个进程调用的时候,会写乱这个全局数据结构,或者api内部调用了malloc或者free在修改链表的时候。

 

可靠信号术语和语义

在信号产生和递送之间的时间间隔内,称信号是未决的。

每一个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集,对于每种可能的信号,该屏蔽字都有一位与之相对应,对于某种信号,若其对应位已经被设置则他当前是阻塞的

 

int kill(pid_t pid, int signo)
int raise(int signo);

pid 为

>0             向进程pid发送信号

<0              向进程为|pid|的进程发送信号

==0          向调用的进程组中的每一个进程发送信号。而且有向这些进程发送信号的权限。

==-1          向所有进程发送信号,必须有权限。

有权限的定义是:发送者的实际或者有效用户ID必须等于接受者的实际或者有效用户ID

 

alarm和pause新哈皮

unsigned int  alarm(unsigned int seconds);

向进程发送SIGALRM信号,其默认动作是终止该进程

alarm在设置闹钟时间的时候,如果之前进程设置了另外一个闹钟时间,那么alarm就返回之前的剩余值。

如果seconds为0表示取消以前的闹钟

 

int pause()

pause函数使调用进程挂起知道捕捉到一个信号,只有执行了一个信号处理程序,并从中返回,pause才会返回。

 

信号集

sigset_t 表示信号集

函数

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t* set);
int sigaddset(sigset_t *set, int signo);
int sigdeleteset(sigset_t* set, int signo);
int sigismember(const sigset_t* set, intsigno):

设置信号屏蔽字

int sigprocmask(int how, constsigset_t  *set, sigset_t  *oset);

how:用于指定信号修改的方式,可能选择有三种
SIG_BLOCK //加入信号到进程屏蔽。
SIG_UNBLOCK //从进程屏蔽里将信号删除。
SIG_SETMASK //将set的值设定为新的进程屏蔽。

 

查看当前进程中未决的信号

int sigpending(sigset_t *set),在set中获取当前进程未决的信号集类型

 

sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。

他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该使用这个接口)

给信号signum设置新的信号处理函数act,同时保留该信号原有的信号处理函数oldact

int sigaction(int signo,const struct sigaction *restrict act,

              struct sigaction *restrict oact);

结构sigaction定义如下:

struct sigaction{
  void (*sa_handler)(int);
   sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};

sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flag是一个选项,主要理解两个

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启

SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

 

 

sigsetjmp和siglongjmp

1. 原型:

#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);

直接调用则返回0, 从siglongjmp调用返回则返回非0值.
void siglongjmp(sigjmp_buf env, int val);

可见发现sigsetjmp比setjmp多了一个参数savemask, 如果非0, 则sigsetjmp在env中保存进程的当前信号屏蔽字

 

sigsuspend函数

      #include <signal.h>
       int sigsuspend(const sigset_t *sigmask)

也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接受到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。

 

void abot()函数向进程发送SIGABRT信号

抱歉!评论已关闭.