signal和alarm实现不精确的定时功能
1、alarm()函数
引用头文件:#include <unistd.h>;
函数标准式:unsigned int alarm(unsigned int seconds);
功能与作用:alarm()函数的主要功能是设置信号传送闹钟,即用来设置信号SIGALRM在经过参数seconds秒数后发送给目前的进程。
如果未设置信号SIGALARM的处理函数,那么alarm()默认处理终止进程。
函数返回值:如果在seconds秒内再次调用了alarm函数设置了新的闹钟,则后面定时器的设置将覆盖前面的设置,即之前设置的秒数被新的闹钟时间取代;
当参数seconds为0时,之前设置的定时器闹钟将被取消,并将剩下的时间返回。
2、Signal ()函数
设置某一信号的对应动作。
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
第一个参数signum:指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
第二个参数handler:描述了与信号关联的动作。
此函数必须在signal()被调用前申明,handler中为这个函数的名字。当接收到一个类型为sig的信号时,就执行handler 所指定的函数。
(int)signum是传递给它的唯一参数。执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。
当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。
3、定时器举例
#include <stdio.h> #include <unistd.h> #include <signal.h> void sigalrm_fn(int sig) { printf("alarm!\n"); alarm(2); return; } int main(void) { signal(SIGALRM,signalrm_fn); alarm(2); while(1) pause(); }
运行结果:每隔2秒钟就会输出一次。 alarm! alarm! alarm!
4、信号
信号的处理:信号的处理有三种方法,分别是:忽略(SIG_IGN)、捕捉和默认动作(SIG_DFL)
1)忽略信号,大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILL
和SIGSTOP
)。
因为他们向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的的进程,显然是内核设计者不希望看到的场景
2)捕捉信号,需要告诉内核,用户希望如何处理某一种信号,说白了就是写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
3)系统默认动作,对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。不过,对系统来说,大部分的处理方式都比较粗暴,就是直接杀死该进程。
具体的信号默认动作可以使用man 7 signal
来查看系统的具体定义。
signal(SIGPIPE,SIG_IGN);#忽略管道信号
参考:
https://www.cnblogs.com/wuyepeng/p/9788889.html
https://blog.csdn.net/yyyljw/article/details/80741264
https://www.jianshu.com/p/f445bfeea40a