定时器
话说网络程序通常需要处理的三类事件:第一是IO事件,第二是信号,第三就是定时事件,比如定期检测一个客户连接的状态,定时指的是一段时间后触发某段代码的机制.
为了实现一个定时器容器,我们选择用链表来实现,可按触发时间来排序存储,每个节点都是一个定时器,储存着:
- 触发时间和触发事件
- 所处理的对象
- 上一个和下一个定时器的位置
再设计一个脉搏函数,每次间隔最小时间后就调用,然后将容器中所有到时的定时器触发.
时间轮
如果按上述方式实现定时器,则插入的时间为O(n),效率随着定时器增加而降低,所以我们根据哈希的思想,用空间换时间,改用时间轮的方法.
用两个轮,小轮走一圈,大轮走一格,每个槽上都有一个链表,存储时间是该轮整数倍的定时器.
实现代码:
除了时间轮之外,还有的实现方法为时间堆.
信号量
信号量是用来解决多进程之间的同步问题,总共有三个系统调用:semget,semop,semctl
|
|
key参数用来全局唯一表示一个信号量集,要通过信号量通信的进程需要使用相同的键值来创建/获取该信号量.
num_sems指定要创建/获取的信号量集中信号量的数目,获取信号量可设置0\
sem_flags指定一组标志
semget成功返回一个正整数值,他是信号量集的标示符,创建信号量集内核中关联的数据结构体semid_ds将被创建:
semop系统调用改变信号量的值,主要改变内核中如下变量:
unsigned short semval;//信号量的值
unsigned short semzcnt; //等待信号量值变为0的进程数量
unsigned short semncnt;//等待信号量
pid_t sempid;//最后一次执行semop操作的进程ID
进程池
实现一个进程池,池中所有的子进程都运行着相同的代码,并具有相同的属性,比如优先级,PGID,因为进程池在服务器启动之初就创建好了
主进程选择子进程算法有随机选取和轮流选取算法
主进程管理所有监听socket,如果有新的连接,通知子进程调用accept接受,无需传递连接socket
我们用一个全局管道来统一事件源,为了让进程收到的信号不中断进程,用管道接受信号,然后注册到epoll内核事件表一起监听.
每个子进程都有一个管道用来与父进程通信,主要是父进程通过管道通知子进程有新的连接到来.
|
|
线程同步
为了使用方便,我们将posix线程标准下用来同步线程的三种锁进行封装,信号量,互斥量,条件变量
|
|