信号的捕捉
信号捕捉过程:
- 定义新的信号的执行函数handle。
- 使用signal/sigaction 函数,把自定义的handle和指定的信号相关联。
signal函数:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:捕捉信号执行自定义函数
返回值:成功时返回原先的信号处理函数,失败时返回SIG_ERR
参数:
signo 要设置的信号类型
handler 指定的信号处理函数: SIG_DFL代表缺省方式; SIG_IGN 代表忽略信号;
系统建议使用sigaction函数,因为signal在不同类unix系统的行为不完全一样。
sigaction函数:
int sigaction(int signum, const struct sigaction *act,struct sigaction *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);
}
参数:
signum:处理的信号
act,oldact: 处理信号的新行为和旧的行为,是一个sigaction结构体。
sigaction结构体成员定义如下:
sa_handler: 是一个函数指针,其含义与 signal 函数中的信号处理函数类似
sa_sigaction: 另一个信号处理函数,它有三个参数,可以获得关于信号的更详细的信息。
sa_flags参考值如下:
SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数
SA_RESTART:使被信号打断的系统调用自动重新发起。
SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
re_restorer:是一个已经废弃的数据域
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/posix_types.h>
typedef void (*sighandler_t)(int);
sighandler_t oldact;
void handle(int sig)
{
if (sig == SIGINT)
{
printf("I cath the SIGINT \n");
}
else if (sig == SIGALRM)
{
printf("second timer \n");
alarm(1);
}
// signal(SIGINT,oldact);
}
void mytimer(int sig)
{
}
int main()
{
struct sigaction act;//定义结构体
act.sa_handler = handle;//结构体成员初始化
act.sa_flags = 0;
sigemptyset(&act.sa_mask);//清空信号集
sigaction(SIGINT, &act, NULL);//捕捉ctr+c信号
alarm(1);
sigaction(SIGALRM, &act, NULL);//捕捉alarm信号
// oldact = signal(SIGINT,handle);
while (1)
{
sleep(1);
}
}
定时器的实现
ualarm(循环发送)
useconds_t ualarm (useconds_t usecs, useconds_t interval);
以 useconds 为单位,第一个参数为第一次产生时间,第二个参数为间隔产生
int setitimer (int which, const struct itimerval *new_value, struct itimerval *old_value);
功能:定时的发送 alarm 信号参数:
which:
ITIMER_REAL:以逝去时间递减。发送 SIGALRM 信号
ITIMER_VIRTUAL:计算进程(用户模式)执行的时间。发送 SIGVTALRM 信号
ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计算时间。发送 SIGPROF 信号
ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计算时间。发送 SIGPROF 信号
new_value:负责设定 timout 时间
old_value:存放旧的 timeout 值,一般指定为
NULL struct itimerval{
struct timeval it_interval;//闹钟触发周期
struct timeval it_value;//闹钟触发时间
};
struct timeval {
time_t ty_sec /*seconds */
suseconds_t ty_usec / microseconds
}
通过信号捕捉实现定时捕捉alarm信号
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/posix_types.h>
#include <sys/time.h>
typedef void (*sighandler_t)(int);
sighandler_t oldact;
void handle(int sig)
{
if (sig == SIGINT)
{
printf("I cath the SIGINT \n");
}
else if (sig == SIGALRM)
{
printf("second timer \n");
// alarm(1);
}
// signal(SIGINT,oldact);
}
int main()
{
struct sigaction act;
act.sa_handler = handle;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
// sigaction(SIGINT,&act,NULL);
// alarm(1);
struct itimerval timevalue;
timevalue.it_interval.tv_sec = 1;//闹钟触发周期 时间间隔1S
timevalue.it_interval.tv_usec = 0;//闹钟触发周期
timevalue.it_value.tv_sec = 5;//闹钟触发时间 5s启动定时器
timevalue.it_value.tv_usec = 0;//闹钟触发时间
setitimer(ITIMER_REAL, &timevalue, NULL);//定时发送alarm信号
sigaction(SIGALRM, &act, NULL);//捕捉alarm信号
// oldact = signal(SIGINT,handle);
while (1)
{
// sleep(1);
}
}
使用SIGCHLD信号实现回收子进程
SIGCHLD的产生条件
1子进程终止时
2子进程接收到SIGSTOP信号停止时
3子进程处在停止态,接受到SIGCONT后唤醒时
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
//处理信号函数
void handle(int sig)
{
wait(NULL);//回收子进程,阻塞进程
printf("Get sig =%d\n", sig);
}
int main()
{
pid_t pid;
struct sigaction act;
act.sa_handler = handle;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
pid = fork();
if (pid > 0)
{
//wait(NULL);
sigaction(SIGCHLD, &act, NULL);//捕捉alarm信号
while (1)
{
printf("this is father process\n");
sleep(1);
}
}
else if (pid == 0)
{
sleep(5);
exit(0);//子进程退出
}
}