Reactor
Reactor 要求主线程或内核负责监听文件描述符是否有事件发生,有的话立刻告知线程.数据读写全部由控制线程负责.同步io
epoll就是这种方式
组件
event demultiplexer
事件多路分发器,如select,poll,epoll
handle
事件源:用于识别每一个事件,Linux上是文件描述符Reactor
反应器,用于管理事件的调度和注册删除event handler
事件处理器:管理已经注册的事件和已经激活等待调度的事件,并分成了不同类型的事件(如读/写、信号),当事件发生时,会提供对应的处理程序。由Reactor
调用。
Proactor
Proactor 所有io操作由主线程或者内核负责,控制线程只负责业务逻辑,异步io
aio
timewait
TCP四次挥手中,主动方在发送第二个ACK后的2MSL(max segment lifetime)时间之内,RFC推荐是2MSL=120,Linux内核2MSL=60s
目的:防止ACK包丢失,等待是否有被动方重发的seq
解决方法:
- 编程时使用
SO_REUSEADDR
- Linux里
1
2
3
4
5
6
7
8# 启动TCP ts,tcp_tw_reuse和.tcp_tw_recycle依赖此实现
net.ipv4.tcp_timestamps=1
# 复用TIME_WAIT的socket
net.ipv4.tcp_tw_reuse=1
# 销毁TIME_WAIT的socket,由于nat可能会导致无法握手
net.ipv4.tcp_tw_recycle=1
# 重设超时
net.ipv4.tcp_fin_timeout=30- 编程时使用
Linux IO模型
- 阻塞IO
- 非阻塞IO
- IO复用
- 信号驱动IO
- 异步IO
僵尸进程解决
两次fork.父进程创建子进程,子进程负责fork孙子进程,孙子进程负责执行逻辑业务,子进程fork完孙子线程后直接exit.孙子进程变成孤儿线程,交由init管理
子进程在结束时会向父线程发送
SIGCHLD
.父进程只要在信号处理函数中wait,进行子进程的PCB进行回收1
2
3
4
5
6
7
8
9
10
11static void sig_child(int signo) {
pid_t pid;
int stat;
//处理僵尸进程
while ((pid = waitpid(-1, &stat, WNOHANG)) >0)
printf("child %d terminated.\n", pid);
}
int main() {
signal(SIGCHLD, sig_child);
......
}忽略请求
1
signal(SIGCLD, SIG_IGN);
一致性hash
哈希值映射到圆环,节点分布在环上,顺时针的第一个节点就是数据存取节点
RVO (return value optimization) 和NRVO (named return value optimization)
Traits
被其他object或algorithm使用的,用来携带信息的object
实现:模板的特化与偏特化