目录
1. 信号的基本
1.1 信号的特点
- 信号是消息的载体
- 信号是一种软中断
1.2 信号的默认行为
term --- 终止一个进程
ign --- 忽略
core --- 终止进程,产生core文件
stop --- 停止一个进程
con --- 继续运行
1.3 常见的信号
SIGINT(2) --- term --- ctrl+C
SIGQUIT(3) --- core --- ctrl+\
SIGKILL(9) --- term
SIGSEGV(11) --- core --- 访问无效内存
SIGPIPE(13) --- term --- 写一个读端关闭的通道
SIGALRM(14) --- term --- 时钟信号
SIGUSR1(10) --- term --- 用户自定义
SIGUSR2(12) --- term --- 用户自定义
1.4 信号的处理
默认处理:以默认方式处理。
忽略:进程继续运行,忽略对信号的处理。
捕捉信号并处理:进程实现定义信号处理函数,接收到信号时由函数自动捕捉并处理。
2. 信号的注册
2.1 signal
//信号处理函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
//handler:结构体指针,指向信号处理函数
//成功返回结构体指针,失败返回SIG_ERR
2.2 sigaction
可移植性更强
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
//act:结构体指针,指向处理信号的结构体
//结构体
struct sigaction {
//旧类型的信号处理函数
void (*sa_handler)(int);
//新类型的信号处理函数
//siginfo_t指向siginfo_t结构体,结构体存储详细的信号信息
//void*指向ucontext_t结构体,结构体包含内核保存在用户空间上信号的上下文信息
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
//恢复系统调用
act.sa_flags = SA_RESETHAND
NOTICE: 若同时使用新旧类型,会优先使用最后调用的类型。
理由:新旧类型是一个联合体
struct sigaction {
union {
__sighandler_t _sa_handler;
void (*_sa_sigaction)(int, struct siginfo *, void *);
} _u;
sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
3. 四种情形
情形一:处理完一个信号,是否需要重新注册捕捉下一个信号 --- 不需要
情形二:信号处理过程中收到一个同类型的信号 --- 只会多执行一次,忽略其他信号
情形三:信号处理过程中收到一个不同类型的信号 --- 立即处理,且后续相同类型的信号只会处理
一次,完成后再处理原信号
情形四:进程正阻塞在系统调用上,此时收到一个信号
--- 对signal,会优先处理信号的行为,再重新阻塞
--- 对sigaction,会优先处理信号的行为,不会继续阻塞,系统调用返回失败
4. 信号的阻塞
4.1 忽略和阻塞
- 忽略:不作任何处理
- 阻塞:不会立即处理,过一段时间再执行
4.2 sigaction实现局部阻塞
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
//set:保存阻塞信号的集合
sigset_t set;
sigempty(&set);
sigaddset(&set,SIGNAL);
act.sa_mask = set;
4.3 sigprocmask实现全局阻塞
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
//how: 处理方式 --- SIG_BLOCK | SIG_UNBLOCK | SIG_SETMASK
//set:存储需要阻塞的信号的集合
//可设置阻塞范围,实现全局阻塞
4.4 查看阻塞的信号
//查看系统中阻塞的信号
int sigpending(sigset_t *set);
//判断信号是否在集合中
int sigismember(const sigset_t *set, int signum);
//在集合中返回1,不在返回0,失返回-1
5. kill信号
NOTICE: 9和19号信号无法被捕捉!
int kill(pid_t pid, int sig);
//pid > 0 --- 给pid指的进程发送信号
//pid = 0 --- 给包括调用进程在内的同组的每一个进程发送信号
//pid = -1 --- 广播信号,给系统中除init和自己外的所有进程发送信号
//pid < -1 --- 向gid == |pid|的进程组的所有下属进程发送信号
6. 计时器
6.1 分类
- 真实计时器:计算从程序启动到当前时刻实际运行的时间 SIGALRM
- 虚拟计时器:计算程序在用户态消耗的是时间(不包含系统调用及睡眠时间)SIGVTALRM
- 实用计时器:计算程序在用户态及内核态消耗的时间 SIGPROF
6.2 实现
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
//which:使用的计时器种类 --- ITIMER_REAL | ITIMER_VIRTUAL | ITIMER_PROF
//curr_value:指向itimerval结构体,该结构体保存计时器相关信息
struct itimerval{
struct timeval it_interval; //重复间隔时间
struct timeval it_value; //初始间隔
};
struct timeval{
time_t tv_sec;
suseconds_t tv_usec;
};