Web服务器的定时器

参考:
最新版Web服务器项目详解 - 07 定时器处理非活动连接(上)
最新版Web服务器项目详解 - 08 定时器处理非活动连接(下)

我的误区:

  1. sigaction结构体中的 sigset_t sa_mask
struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}

sa_mask用来指定在信号处理函数执行期间需要被屏蔽的信号。只是指定处理期间需要屏蔽的而已。

  1. sigfillset函数
#include <signal.h>

int sigfillset(sigset_t *set);

用来将参数set信号集初始化,然后把所有的信号加入到此信号集里。
与sigaction结构体中的sa_mask联用,实现在处理信号时屏蔽其他所有信号。

  1. socketpair函数
    在linux下,使用socketpair函数能够创建一对套接字进行通信,项目中使用管道通信。

  2. send函数
    曾经我也很疑惑如何判断缓冲区可写。实际上缓冲区非满时理论上就可写?
    当套接字发送缓冲区变满时,send通常会阻塞,除非套接字设置为非阻塞模式,当缓冲区变满时,返回EAGAIN或者EWOULDBLOCK错误,此时可以调用select(epoll EPOLLOUT?)函数来监视何时可以发送数据。

  3. 统一事件源
    统一事件源,是指将信号事件与其他事件一样被处理。
    也就是都放在主循环中,同其他信号事件一样被处理。

  4. 信号处理机制
    image

接收信号的任务是由内核代理的,当内核接收到信号后,会将其放到对应进程的信号队列中,同时向进程发送一个中断,使其陷入内核态。注意,此时信号还只是在队列中,对进程来说暂时是不知道有信号到来的。

进程陷入内核态后,有两种场景会对信号进行检测:?

  • 进程从内核态返回到用户态前进行信号检测
  • 进程在内核态中,从睡眠状态被唤醒的时候进行信号检测

当发现有新信号时,便会进入下一步,信号的处理。

( 内核 )信号处理函数是运行在用户态的,调用处理函数前,内核会将当前内核栈的内容备份拷贝到用户栈上,并且修改指令寄存器(eip)将其指向信号处理函数。

( 用户 )接下来进程返回到用户态中,执行相应的信号处理函数。

( 内核 )信号处理函数执行完成后,还需要返回内核态,检查是否还有其它信号未处理。

( 用户 )如果所有信号都处理完成,就会将内核栈恢复(从用户栈的备份拷贝回来),同时恢复指令寄存器(eip)将其指向中断前的运行位置,最后回到用户态继续执行进程。

至此,一个完整的信号处理流程便结束了,如果同时有多个信号到达,上面的处理流程会在第2步和第3步骤间重复进行。

posted @ 2023-10-24 22:27  HDD-SG  阅读(35)  评论(0)    收藏  举报