织梦CMS - 轻松建站从此开始!

罗索

Linux下的信号编程小结

jackyhwei 发布于 2010-01-26 11:44 点击:次 
不可靠信号假如一个进程接收到一个普通信号,而进程的未决信号集(pending signals)中存在相同的信号,则这个新发送的信号丢失。即同一时间进程的未决信号集中只可能有一个普通信号。
TAG:

Linux下的信号编程小结

1 概念
1.1 产生条件
- 用户按下了某些终端键(如Ctrl-c)时
- 硬件异常产生信号
- 进程用kill(2)函数给另一个进程或进程组发送信号
- 用户用kill(1)命令发送信号给进程
- 某种软件条件发生(如SIGPIPE等信号)
1.2 动作
- 忽略此信号
- 捕获信号
- 执行系统默认动作
1.3 信号分类
-不可靠信号,即普通信号。假如一个进程接收到一个普通信号,而进程的未决信号集(pending signals)中存在相同的信号,则这个新发送的信号丢失。即同一时间进程的未决信号集中只可能有一个普通信号。文档/usr/include/bits/signum.h中定义了任何普通信号。
-可靠信号,即实时信号。信号值在SIGRTMIN(32)和SIGRTMAX(64)之间的信号。实时信号每次都会被加入到未决信号集中。
2 signal函数
2.1 函数原形
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
2.2 说明
handler的值能够是SIG_IGN(忽略信号),SIG_DFL(默认行为)或是用户自定义的一个信号处理函数。返回的是之前的信号处理函数指针或SIG_ERR。
3 中断的系统调用
假如进程执行一个低速系统调用而阻塞期间捕获到一个信号,该系统调用会被中断返回出错,errno设为EINTR。4.2BSD引入了自动再启动的系统调用包括:read、readv、write、writev、ioctl、wait和waitpid。
4 可再入函数
不可再入函数一般是指:a)使用了静态数据结构,b)调用了malloc或free或c)标准I/O函数。假如在信号处理函数种调用不可再入函数,则可能会引起错误。
即使是可载入函数,因为errno每个进程只有一个,也有可能引起错误。因此一般调用使用errno的系统调用之前都要保存errno,在调用后再恢复。
5 发送等待信号
5.1 相关函数
int kill(pid_t pid, int sig);
int raise(int sig);
unsigned int alarm(unsigned int seconds);
int pause(void);
5.2 说明
kill能够给人以进程发送信号,raise则给当前进程发送信号。
alarm则配置一个闹钟值,所配置的时间超过后,产生一个SIGALARM信号,其默认动作时终止该进程。
pause是当前进程挂起直到接收到一个信号。
实例:
- sleep的不完整的实现:signals/sleep1.c
6 信号集
6.1 相关函数
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
6.2 说明
sigset是表示多个信号的数据类型。sigemptyset函数使信号集set不包含任何信号,sigfillset使set包含任何的信号。sigaddset和sigdelset添加和删除一个信号。sigismember检测信号集是否包含特定的信号。
7 POSIX信号处理函数
7.1 相关函数
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigpending(sigset_t *set);
int sigsuspend(const sigset_t *mask);
7.2 说明
用sigprocmask设定进程信号屏蔽字,参数how有三个可选项:SIG_BLOCK,SIG_UNBLOCK和SIG_SETMASK。
sigpending返回对于调用进程被阻塞的和当前未决的信号集。
sigaction取代了早期的signal函数,用于设定和信号相关联的处理动作。参数act的类型为:
struct sigaction {
       void (*sa_handler)(int);
       void (*sa_sigaction)(int, siginfo_t *, void *);
       sigset_t sa_mask;
       int sa_flags;
}
因为可能会用union实现,只能给两个信号处理函数指针sa_handler和sa_sigaction中的一个赋值。sa_mask是信号处理函数执行时应该被屏蔽的信号。flag则是一些标识,要使用sa_sigaction则必须设定SA_SIGINFO,这样信号的一些信息及传递的变量才会被配置到sa_sigaction的第二个参数中。关于sa_sigaction第二个参数的使用,参看man文档。
sigsuspend以参数mask为屏蔽字是进程挂起直到接收到一个信号。相当于以原子操作实现:
sigprocmask(SIG_SETMASK, &mask, &oldmask);
pause();
sigprocmask(SIG_SETMASK, &oldmask, NULL);
实例:
- 父子进程同步的实现:lib.rhlin /tellwait.c
- 用sigsuspend保护临界区:signals/suspend1.c
- 用sigsuspend等待一个全局变量被配置:signals/suspend2.c
- abort的实现:signals/abort.c
- system的POSIX.2实现:signals/system.c
- 处理SIGTSTP信号(Ctrl-z):signals/sigtstp.c
8 非局部跳转
8.1 相关函数
int sigsetjmp(sigjmp_buf env, int savesigs);
void siglongjmp(sigjmp_buf env, int val);
8.2 说明
这两个函数和setjmp、longjmp之间的唯一区分是sigsetjmp增加了一个参数。savesigs为非0,则sigsetjmp在env中保存进程的当前屏蔽字。
实例:
- 信号屏蔽及siglongjmp的使用:signals/mask.c 

原文:http://hi.baidu.com/amy_yeni/blog/item/7a385ccc549b28590fb345ba.html

(amy_yeni)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201001/8392.html]
本文出处:hi.baidu.com 作者:amy_yeni
顶一下
(0)
0%
踩一下
(1)
100%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容