Epoll 之 Redis 自行向下
Wirte by 021. Leave a message if i messed up ! : )
IO 进化史
BIO阻塞IO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| //有1000个客户端读文件描述符的需求 files waitRead = read(fd)*1000;
1, file = read(waitRead[0]);
2, if(file != null) { //do work }
//单线程阻塞, 只能使用多线程处理, 每一条线程处理一个文件描述符的读取系统调用
new Thread(
files waitRead = read(fd)*1000;
1, file = read(waitRead[0]);
2, if(file != null) { //do work } ).start();
|
NIO同步非阻塞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| //有1000个读文件描述符的需求 read(int fd) * 1000;
for(;;) {
for(1000 * fd) // 用户空间 系统调用轮询1000次, { file = read(fd1~fd1000); //轮询读取每一个fd文件描述符,不管数据有没有准备好 if(file != null) { // do work.... } } }
|
Select(多路复用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| //有1000个读文件描述符的需求 read(int fd) * 1000;
//select 系统调用函数, 一次性传输多个文件描述符传输给内核,返回准备好的文件描述; select(fd*1000);
file fds = select(fd*1000); // 系统调用,内核返回准备好的文件的描述符 for( 0;fds; ) // 用户空间遍历内核返回的全部文件描述符, { if(fd.readAble) //检测文件可读状态 { file = read(fd); if(file != null) { // do work.... } } }
|
epoll
模拟内核 和 用户 共享空间逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 模拟原始内存空间:
0xffffffff ------------用户空间-------------0x80000000 ------------内核空间------------ 0x00000000;
模拟共享空间: //用户与内核 映射 同一块物理空间
0xffffffff ---------用户空间---------[0x80000000 ---共享空间--- 0x700000000 ]------内核空间----- 0x00000000;
// 共享空间容器 1,红黑树 - 等待读取的文件描述符 ,btree; 2,链表 - 准备好的文件描述符 , readyLinkList;
btree.add(epoll.creat(fd)); // 将待读取的文件描述符 放入共享空间的红黑树.
file = read(readyLinkList(fd)); //读取 共享空间 链表容器 已准备好的文件描述符;
|
redis 单进程 单线程 为什么快?