C标准库<signal.h>实现
本文地址:http://www.cnblogs.com/archimedes/p/c-library-signal.html,转载请注明源地址。
背景知识
signal.h是C标准函数库中的信号处理部分, 定义了程序执行时如何处理不同的信号。信号用作进程间通信, 报告异常行为(如除零)、用户的一些按键组合(如同时按下Ctrl与C键,产生信号SIGINT)。信号是程序执行过程中发生的异常事件,同步信号的产生是因为程序自身的某些动作,例如除零或不正当的访问存储器,异步信号是由程序外部的行为引起的,比如有人敲击了提示键或者另外一个程序(异步地执行)给你的程序发信号,都会引发一个异步信号。程序不能屏蔽的信号要求立即得到处理。如果不对发生的信号指定一种处理方法,那么它就会被作为一种致命错误对待,然后程序就会以失败的状态终止执行
头文件<singal.h>定义了一个无穷信号集的各种编码值:
#define _NSIG 16 //能够使用的信号的数量 #define SIGHUP 1 // 挂起
#define SIGINT 2 // 中断 (DEL)
#define SIGQUIT 3 // 退出 (ASCII FS)
#define SIGILL 4 // 非法指令
#define SIGTRAP 5 // 跟踪中断 (捕捉的时候没有重置)
#define SIGABRT 6 // IOT 指令
#define SIGIOT 6 // 终止使用PDP-11
#define SIGUNUSED 7 // 备用代码
#define SIGFPE 8 // 浮点型异常
#define SIGKILL 9 // kill (不能捕获或忽略)
#define SIGUSR1 10 // 用户定义信号 # 1
#define SIGSEGV 11 // 内存段异常
#define SIGUSR2 12 // 用户定义信号 # 2
#define SIGPIPE 13 // 在管道上写操作没有其他的读操作
#define SIGALRM 14 // 警告
#define SIGTERM 15 // kill后获得软件终止信号 #define SIGEMT 7 // 旧式
#define SIGBUS 10 // 旧式 /* POSIX 要求定义下面的信号, 即使它们不被支持. 这里给出这些定义, 但是它们不被支持. */
#define SIGCHLD 17 // 子进程终止或停止
#define SIGCONT 18 // 如果停止则继续
#define SIGSTOP 19 // 停止信号
#define SIGTSTP 20 // 交互式停止信号
#define SIGTTIN 21 // 后台进程试图读
#define SIGTTOU 22 // 后台进程试图写
两个函数:
raise函数,报告一个同步信号
int raise (int _sig);
signal函数,可以指定一种信号的处理方法
__sighandler_t signal (int _sig, __sighandler_t _func) ;
可以通过一下三种方式处理信号:
默认处理是终止程序,就像上面所描述的那样
信号忽略是直接把它丢弃
信号处理是把控制权移给一个指定的函数
C标准的内容
头文件 <signal.h>为处理各种各样的信号声明了一个类型和两个函数,并定义了几个宏
定义的类型是:sig_atomic_t
typedef int sig_atomic_t;
该类型是整数类型,声明为这种类型的对象可以作为一个原子实体被访问,即使有异步中断发生的时候也是如此。
定义的宏有: SIG_DFL、SIG_ERR、SIG_IGN
#define SIG_ERR ((__sighandler_t) -1) // 出错返回值
#define SIG_DFL ((__sighandler_t) 0) // 默认信号处理
#define SIG_IGN ((__sighandler_t) 1) // 忽略信号
它们展开为具有不同值的常量表达式,这些表达式的类型和函数signal的第二个参数及返回值的类型兼容,并且它们的值与所有声明的函数的地址都不相等。
指定信号处理
函数signal:
typedef void (*__sighandler_t) (int);
__sighandler_t signal(int _sig, __sighandler_t _func);
或声明成:
void (*signal(int sig, void (*func) (int)))(int);
signal函数通过3种方式来保证接收到的信号编号sig被依次处理,如果func的值是SIG_DFL,那么会使用默认的信号处理方式;如果func的值是SIG_IGN,那么这个信号就会被忽略;否则,func就指向一个函数,当这个信号发生时,就调用这个函数,这样的函数就被称为信号处理程序。
函数raise:
int raise(int sig);
函数raise把信号sig送给正在执行的程序
返回值:执行成功返回0,否则返回非0
<singal.h>的使用
从本质上说,信号处理是不可移植的。只有当必须指定一个已知的操作系统集的信号处理时,才能使用<signal.h>中声明的函数,不用费尽心思把代码变成通用的,这是不可能的
如果对一个信号的默认处理是可行的,那么就选择这种处理方法,使用自己的信号处理程序会降低可移植性并且可能导致程序对信号的误处理增多,如果必须提供某个信号的处理程序,对其进行分类如下:
不可能返回值的信号处理程序,e.g:SIGFPE和SIGABRT
必须返回值的信号处理程序,e.g:SIGINT
不能返回值的信号处理程序最后会调用abort、exit或者longjmp来结束。当然,SIGABRT的处理程序不能调用abort来结束。处理程序不应该调用singal使自己重建。如果程序没有终止,就把剩下的工作给其他的函数。如果信号是异步的,要注意程序所有的输入输出,因为这样的操作也会中断库的执行。
必须返回的信号处理程序用一个return语句结束,如果它想让自己复位,那么应该在入口处立即返回。如果信号是异步的,就在一个sig_atomic_t类型的volatile数据对象中存储一个非零值。不要执行其他任何对正在执行的程序有副作用的动作,例如输入输出和访问其他的数据对象
<singal.h>的实现
下面是一个异步信号处理程序的例子:
#include<signal.h>
static sig_atomic_t intflag = ;
static void field_int(int sig) {
signal(SIGINT, &field_int);
intflag = ;
return;
}
这个程序调用signal(SIGINT, &field_int)来创建处理程序。它会不时地执行下面的代码来检查是否发生了异步交互式提示中断:
if(intflag) {
//执行中断
intflag = ;
...
}
raise.c
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
_sigfun *_sigtable[_NSIG] = {};
int raise(int sig)
{
_sigfun *s;
if(sig <= || _NSIG <= sig)
return -;
if((s = _sigtable[sig]) != SIG_IGN && s!= SIG_DFL) {
_sigtable[sig] = SIG_DFL;
(*s)(sig);
} else if (s == SIG_DFL) {
char ac[], *p;
switch(sig) {
case SIGABRT:
p = "abort";
break;
case SIGFPE:
p = "arithmetic error";
break;
case SIGILL:
p = "invalid executable code";
break;
case SIGINT:
p = "interruption";
break;
case SIGSEGV:
p = "invalid storage access";
break;
case SIGTERM:
p = "termination request";
break;
default:
*(p = &ac[sizeof(ac) - ]) = '\0';
do
*--p = sig % + '';
while((sig /= ) != );
fputs("signal #", stderr);
break;
}
fputs(p, strerr);
fputs(" -- terminating\n", stderr);
exit(EXIT_FAILURE);
}
return ;
}
signal.c
#include<signal.h>
_sigfun *_sigtable[_NSIG];
_sigfun *signal(int sig, _sigfun *fun)
{
_sigfun *s;
if(sig <= || _NSIG <= sig || fun == SIG_ERR)
return SIG_ERR;
s = _sigtable[sig];
_sigtable[sig] = fun;
return s;
}
C标准库<signal.h>实现的更多相关文章
- C 标准库 - ctype.h
C 标准库 - ctype.h This header declares a set of functions to classify and transform individual charact ...
- C标准库<ctype.h>实现
本文地址:http://www.cnblogs.com/archimedes/p/c-library-ctype.html,转载请注明源地址. 1.背景知识 ctype.h是C标准函数库中的头文件,定 ...
- C 标准库 - ctype.h之iscntrl 使用
iscntrl int iscntrl ( int c ); Check if character is a control character 检查给定字符是否为控制字符,即编码 0x00-0x1F ...
- C 标准库 - ctype.h之isalpha使用
isalpha int isalpha ( int c ); Checks whether c is an alphabetic letter. 检查给定字符是否字母字符,即是大写字母( ABCDEF ...
- C 标准库 - ctype.h之isalnum使用
isalnum int isalnum ( int c ); Checks whether c is either a decimal digit or an uppercase or lowerca ...
- C 标准库 - string.h
C 标准库 - string.h This header file defines several functions to manipulate C strings and arrays. stri ...
- C 标准库 - <assert.h>
C 标准库 - <assert.h> 简介 C 标准库的 assert.h头文件提供了一个名为 assert 的宏,它可用于验证程序做出的假设,并在假设为假时输出诊断消息. 已定义的宏 a ...
- C 标准库 - <stdarg.h>
C 标准库 - <stdarg.h> 简介 stdarg.h 头文件定义了一个变量类型 va_list 和三个宏,这三个宏可用于在参数个数未知(即参数个数可变)时获取函数中的参数. 可变参 ...
- C 标准库 - <signal.h>
C 标准库 - <signal.h> 简介 signal.h 头文件定义了一个变量类型 sig_atomic_t.两个函数调用和一些宏来处理程序执行期间报告的不同信号. 库变量 下面是头文 ...
- C 标准库 - <setjmp.h>
C 标准库 - <setjmp.h> 简介 setjmp.h 头文件定义了宏 setjmp().函数 longjmp() 和变量类型 jmp_buf,该变量类型会绕过正常的函数调用和返回规 ...
随机推荐
- 实现TabView(页签)效果
今天花了点时间,设计了一个网页上用的tabview(页签.tabcontrol)效果.个人觉得实现得比较不错,网页元素用得比较少,js代码也比较精练.测试了一下支持IE.FireFox以及chrome ...
- 支付SDK的安全问题——隐式意图可导致钓鱼攻击
该漏洞涉及到app所使用的intent和intent filter. intent是一个可用于从一个app组件请求动作或处理事件的“消息对象”.Intent负责对应用中一次操作的动作.动作涉及数据. ...
- mysql中int、bigint、smallint 和 tinyint的区别详细介绍
1 bytes = 8 bit ,一个字节最多可以代表的数据长度是2的8次方 11111111 在计算机中也就是 -128到127 1.BIT[M] 位字段类型,M表示每个值的位数,范围从1到64,如 ...
- Hadoop入门进阶课程9--Mahout介绍、安装与应用案例
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博主为石山园,博客地址为 http://www.cnblogs.com/shishanyuan ...
- TOGAF:企业信息化复杂吗?
本文更新版本已挪至:http://www.zhoujingen.cn/blog/2666.html -------------------- 在与人交流TOGAF的时候,离不开企业信息化,而信息化又离 ...
- Docker 定制容器镜像的2种方法
一.需求 由于在测试环境中使用了docker官网的centos 镜像,但是该镜像里面默认没有安装ssh服务,在做测试时又需要开启ssh.所以上网也查了查资料.下面详细的纪录下.在centos 容器内安 ...
- Thrift在Windows及Linux平台下的安装和使用示例
本文章也同时发表在个人博客Thrift在Windows及Linux平台下的安装和使用示例上. thrift介绍 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的R ...
- Vim杂记:Sublime的配色方案
一.前言 爱美之心人皆有之,sublime的配色实在好看,于是希望Vim也能这样. 二.配置 1.下载monokai(https://github.com/sickill/vim-monokai),然 ...
- SQL 分类统计函数
SELECT TransactionNumber,SUM(CASE WHEN ReasonLevel=0 THEN TransactionNumber ELSE 0 end ) a ...
- BZOJ1003 物流运输 最短路+DP
1003: [ZJOI2006]物流运输 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条 ...