网络编程教程(八)信号和定时器

一、信号

1.信号 API

(1)发送信号

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
函数功能:
    向进程ID为pid的进程发送信号sig
函数参数:
    pid:进程编号
    sig:信号值
返回值:
    函数成功时返回0,失败则返回-1,并设置errno.

(2)信号处理方式

#include <signal.h>
typedef void (*__sighanlder_t) (int);
函数功能:
    定义一个函数指针,当目标进程收到信号时,就调用该函数指针所指的函数进行处理
函数参数:
    __sighandler_t:函数指针,指向有一个整型参数,而无返回值的函数

2.信号函数

(1)signal系统调用

#include <signal.h>
_sighandler_t signal(int sig, _sighandler_t _handler);
函数功能:
    为信号sig设置处理函数_handler()A
函数参数:
    sig     :信号
    _handler:信号对应的处理函数
返回值:
    成功时返回一个函数指针,该函数指针的类型也是_sighandler_t。这个返回值时前一次调用signal函数时传入的函数指针,或者是信号sig对应的默认处理函数指针SIG_DEF.调用出错时返回SIG_ERR,并设置errno.

(2)sigaction系统调用

#include <signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
函数功能:
    为信号sig设置处理函数
函数参数:
    sig :指定要捕获的信号类型
    act :指定新的信号处理方式
    oact:输出信号先前的处理方式

二、定时器

1.为什么需要定时器

        服务器程序管理者众多的定时时间,因此有效地组织这些定时时间,使之能在预期的时间点被触发且不影响服务器的主要逻辑,对于服务器性能有着至关重要的影响。为此将每个定时事件分别封装成定时器,并使用某种容器类数据结构,比如链表、排序链表和时间轮,将所有定时器串联起来,以实现对定时事件的统一管理。所谓的定时是指在一段时间之后触发某段代码的机制。在这段代码中一次处理所有到期的定时器。

        Linux提供三种定时方法:socket选项SO_RCVTIMEO和SO_SNDTIMEO、SIGALRM信号和I/O复用系统调用的超时参数。

2.SO_RCVTIMEO和SO_SNDTIMEO

        SO_RCVTIMEO和SO_SNDTIMEO分别用来设置socket接收数据超时时间和发送数据超时时间。这两个选项只对send、sendmsg、recv、recvmsg、accept和connect系统调用有效。

注:通过setsockopt()函数设置这个选项。

3.SIGALRM信号

        由alarm和setitimer函数设置的实时闹钟一旦超时,将触发SIGALRM信号。因此,我们可以利用该信号的信号处理函数来处理定时任务。但是,如果要处理多个定时任务,需要不断地触发SIGALRM信号,并在其信号处理函数中执行到期的任务。一般而言,SIGALRM信号按照固定的频率生成,即由alarm或setitimer函数设置的定时周期T保持不变。如果某个定时任务的超时时间不是T的整数倍,那么它实际被执行的事件和预期的时间将略有偏差。

4.I/O复用定时参数

        Linux下的3组I/O复用系统调用都带有超时参数,因此它们不仅能统一处理信号和I/O事件,也能统一处理定时事件。但是由于I/O复用系统调用可能在超时时间到期之前就返回(有I/O事件发生),所以我们如果要利用它们来定时,就需要不断更新定时参数以反映剩余的事件。

5.时间轮

 

        如上图所示,实线指向轮子的一个槽,它以恒定的速度顺时针转动,每转动一步就指向下一个槽(虚线指针指向的槽),每次转动称为一个滴答(tick)。一个滴答的时间称为时间轮的槽间隔si,它实际上就是心博时间。该时间轮共有N个槽,因为它运转一周的事件时N*si.每个槽执行一条定时器链表,每条链表上的定时器具有相同的特征:它们的定时时间相差N*si的整数倍。时间轮正是利用这个关系将定时器散列到不同的链表中。加入现在指针指向槽cs,我们要添加一个定时时间为ti的定时器,该定时器将被插入槽ts对应的链表中:ts=(cs + (ti /si)) % N.

        基于排序链表的定时器使用唯一的一条链表来管理所有定时器,所以插入操作的效率随着定时器数据的增多而降低。而时间轮使用哈希表的思想,将定时器散列到不同链表上。这样每条链表上的定时器数目将明显少于原来的排序链表上的定时器数目,插入操作的效率基本不受定时器数目的影响。

        对时间轮而言,要提高定时精度,就要是si值足够小;要提高执行效率,则要是N值足够大。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值