linux服务器开发相关视频解析:linux下的epoll实战揭秘——支撑亿级IO的底层基石
epoll的网络模型,从redis,memcached到nginx,一起搞定
epoll 是 linux 特有的一个 I/O 事件通知机制 。很久以来对 epoll 如何能够高效处理数以百万记的文件描述符很有兴趣 。近期学习、研究了 epoll 源码,在这个过程中关于 epoll 数据结构和作者的实现思路产生出不少疑惑,在此总结为了 10 个问题并逐个加以解答和分析 。
Question 1:是否所有的文件类型都可以被 epoll 监视?答案:不是 。看下面这个实验代码:
#include <stdio.h>#include <unistd.h>#include <sys/epoll.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#define MAX_EVENTS 1int main (void){ int epfd; epfd = epoll_create(100); /* 创建epoll实例,预计监听100个fd */ if (epfd < 0) { perror ("epoll_create"); } struct epoll_event *events; int nr_events, i; events = malloc (sizeof (struct epoll_event) * MAX_EVENTS); if (!events) { perror("malloc"); return 1; } /* 打开一个普通文本文件 */ int target_fd = open ("./11.txt", O_RDONLY); printf("target_fd %dn", target_fd); int target_listen_type = EPOLLIN; for (i = 0; i < 1; i++) { int ret; events[i].data.fd = target_fd; /* epoll调用返回后,返回给应用进程的fd号 */ events[i].events = target_listen_type; /* 需要监听的事件类型 */ ret = epoll_ctl (epfd, EPOLL_CTL_ADD, target_fd, &events[i]); /* 注册fd到epoll实例上 */ if (ret) { printf("ret %d, errno %dn", ret, errno); perror ("epoll_ctl"); } } /* 应用进程阻塞在epoll上,超时时长置为-1表示一直等到有目标事件才会返回 */ nr_events = epoll_wait(epfd, events, MAX_EVENTS, -1); if (nr_events < 0) { perror ("epoll_wait"); free(events); return 1; } for (i = 0; i < nr_events; i++) { /* 打印出处于就绪状态的fd及其事件 */ printf("event=%d on fd=%dn", events[i].events, events[i].data.fd); } free (events); close(epfd); return 0;}
编译、运行上面的代码,会打印出下列信息:
gcc epoll_test.c -o epdemo./epdemotarget_fd 4ret -1, errno 1epoll_ctl: Operation not permitted
正常打开了"txt"文件 fd=4, 但调用 epoll_ctl 监视这个 fd 时却 ret=-1 失败了, 并且错误码为 1,错误信息为"Operation not permitted" 。错误码指明这个 fd 不能够被 epoll 监视 。
那什么样的 fd 才可以被 epoll 监视呢?
只有底层驱动实现了 file_operations 中 poll 函数的文件类型才可以被 epoll 监视!socket 类型的文件驱动是实现了 poll 函数的,因此才可以被 epoll 监视 。struct file_operations 声明位置是在 include/linux/fs.h 中 。
Question 2:ep->wq 的作用是什么?答案:wq 是一个等待队列,用来保存对某一个 epoll 实例调用 epoll_wait()的所有进程 。
一个进程调用 epoll_wait()后,如果当前还没有任何事件发生,需要让当前进程挂起等待(放到 ep->wq 里);当 epoll 实例监视的文件上有事件发生后,需要唤醒 ep->wq 上的进程去继续执行用户态的业务逻辑 。之所以要用一个等待队列来维护关注这个 epoll 的进程,是因为有时候调用 epoll_wait()的不只一个进程,当多个进程都在关注同一个 epoll 实例时,休眠的进程们通过这个等待队列就可以逐个被唤醒了 。
推荐阅读
- 推荐一个生产环境问题排查利器
- 新网站一直不收录的四个核心问题点
- 主流的四种限流策略,我都可以通过redis实现
- Google Chrome 现已可以通过地址栏运行更多命令
- ps来给人物进行换脸
- 下表列出了东汉后期十个皇帝的即位年龄及寿命,下表列出了东汉后期十个皇帝的即位年龄及寿命
- 如何通过免费的内网穿透工具,让外网访问你本地的服务器?
- 最新Facebook养号流程及常见问题答疑
- 线程安全问题无大小:Java中的线程安全之操作共享数据分类
- PS给人物进行质感修图