1.epoll的工作原理(【360实习】C++开发)
epoll是一种I/O事件通知机制,是linux 内核实现IO多路复用的一个实现。在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其的进行读写操作。
比如调用read一个fd没有就绪就需要阻塞,直到读到数据。即使设置非阻塞,立即返回0,也需要下次再调用read,轮询直到读到数据。而epoll由内核提供了一种机制,只要epoll_wait返回这个fd就绪,那么read这个fd就一定能读到数据。
输入输出的对象可以是文件(file), 网络(socket),进程之间的管道(pipe)。在linux系统中,都用文件描述符(fd)来表示。
- 可读事件,当文件描述符关联的内核读缓冲区可读,则触发可读事件
- 可写事件,当文件描述符关联的内核写缓冲区可写,则触发可写事件。
通知机制,就是当事件发生的时候,则主动通知。通知机制的反面,就是轮询机制。
epoll的通俗解释是一种当文件描述符的内核缓冲区非空的时候,发出可读信号进行通知,当写缓冲区不满的时候,发出可写信号通知的机制。
epoll的核心是3个API,核心数据结构是:1个红黑树和1个链表
int epoll_create(int size)
内核会产生一个epoll 实例数据结构并返回一个文件描述符,这个特殊的描述符就是epoll实例的句柄,后面的两个接口都以它为中心
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
将被监听的描述符添加到红黑树或从红黑树中删除或者对监听事件进行修改
typedef union epoll_data {
void *ptr; /* 指向用户自定义数据 */
int fd; /* 注册的文件描述符 */
uint32_t u32; /* 32-bit integer */
uint64_t u64; /* 64-bit integer */
} epoll_data_t;
struct epoll_event {
uint32_t events; /* 描述epoll事件 */
epoll_data_t data; /* 见上面的结构体 */
};
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
阻塞等待注册的事件发生,返回事件的数目,并将触发的事件写入events数组中。
2.进程间的通信方式,最快的通信方式是什么(【360实习】C++开发)
每个进程都各自拥有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
1.管道/无名管道:
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。
2.命名管道:
也是半双工的通信方式,但是它允许无亲缘关系进程间通信。
3.消息队列:
这三个场景也是消息队列的经典场景,大家基本上要烂熟于心那种,就是一说到消息队列你脑子就要想到异步、削峰、解耦,条件反射那种。
小伙子我打断你一下,你说了异步,那我用线程,线程池去做不是一样的么?
如果各个异步任务,比如扣积分,发短信,扣库存写在一起,不单单是耦合这一个问题,出问题排查也麻烦,流程里面随便一个地方出问题搞不好会影响到其他的点。
但是你用了消息队列,耦合这个问题就迎刃而解了呀。
削峰:就拿我上一期写的秒杀来说,你平时流量很低,但是你要做秒杀活动00 :00的时候流量疯狂怼进来,你的服务器,Redis,MySQL各自的承受能力都不一样,你直接全部流量照单全收肯定有问题啊,直接就打挂了。
把请求放到队列里面,然后至于每秒消费多少请求,就看自己的服务器处理能力,你能处理5000QPS你就消费这么多,可能会比正常的慢一点,但是不至于打挂服务器,等流量高峰下去了,你的服务也就没压力了。
你看阿里双十一12:00的时候这么多流量瞬间涌进去,有时候是不是会慢一点,但是人家没挂啊,或者降级给你个友好的提示页面,等高峰过去了又是一条好汉了。
常见的消息队列包括:kafka(java), rocketmq(java), zmq(cpp)
4.共享内存(最快的 Inter Process Commuication 方式)
两个不同进程 A、B 共享内存的意思是:同一块物理内存被映射到进程 A、B 各自的进程地址空间。比如使用mmap映射出shared的内存空间,进程 A 可以即时看到进程 B 对共享内存中数据的更新,因为进程是直接对内存进行存取,所以最快。
5.套接字socket
此⽅法主要⽤于在客户端和服务器进程之间通过网络进⾏通信。