I/O多路复用之epoll

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在上一章,我们对select进行了大致的描述,知道了它相对传统的阻塞式服务提高了并发度,但是它也由于轮询而导致效率底下。本文对epoll进行讲解,相比select它的并发度更高,现代高负载服务器很多都采用这种模型。
在讲解epoll的具体用法之前,我们先看看采用 epoll模型主要用到的三个函数以及一个数据结构
epoll中三个主要的函数:
(1)int epoll_create(int size);
功能 :生成一个epoll专用的文件描述符。
参数 :size:在该epoll fd上关注的最大socket fd数。
返回值:生成的文件描述符。
(2)int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能 :控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数 :epfd :由 epoll_create 生成的epoll专用的文件描述符;
op :EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除;
fd :关联的文件描述符;
event:指向epoll_event的指针;
返回值:0:成功;
-1:失败;
(3)int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
功能 :轮询I/O事件的发生。
参数 :epfd :由 epoll_create 生成的epoll专用的文件描述符;
events :用于回传待处理事件的数组;
maxevents:每次能处理的事件数;
timeout :等待I/O事件发生的超时值;-1相当于阻塞,0相当于非阻塞;
返回值:>=0 :返回发生事件数;
-1 :错误;

epoll中的主要数据结构:
view source
print ?
01typedef union epoll_data {
02 void *ptr;
03 int fd;
04 __uint32_t u32;
05 __uint64_t u64;
06} epoll_data_t;
07
08struct epoll_event {
09 __uint32_t events; /* Epoll events */
10 epoll_data_t data; /* User data variable */
11};

其中,events的类型有:
EPOLLIN :文件描述符可以读;
EPOLLOUT:文件描述符可以写;
EPOLLPRI:文件描述符有紧急的数据可读;
EPOLLERR:文件描述符发生错误;
EPOLLHUP:文件描述符被挂断;
EPOLLET :文件描述符有事件发生;
epoll的使用还是很简单的,请看下面一个简单的采用epoll提供并发服务的服务端程序(注:为了简洁,都没有进行错误处理,实际使用时,一定要记住进行错误处理。):
view source
print ?
01#include <errno.h>
02#include <string.h>
03#include <sys/types.h>
04#include <netinet/in.h>
05#include <sys/socket.h>
06#include <sys/wait.h>
07#include <unistd.h>
08#include <arpa/inet.h>
09#include <sys/epoll.h>
10#include <sys/time.h>
11
12#define MAXBUF 1024
13#define MAX_EPOLL_SIZE 10000
14#define SERVICE_PORT 8888
15
16
17int main(int argc, char **argv)
18{
19 int server_fd, new_fd;
20 struct sockaddr_in server_addr, client_addr;
21
22 struct epoll_event ev;
23 struct epoll_event events[MAX_EPOLL_SIZE];
24
25 socklen_t len = sizeof(struct sockaddr_in);
26 server_fd = socket(AF_INET, SOCK_STREAM, 0);
27
28 bzero(&server_addr, sizeof(server_addr));
29 server_addr.sin_family = AF_INET;
30 server_addr.sin_port = htons(SERVICE_PORT);
31 server_addr.sin_addr.s_addr = INADDR_ANY;
32
33 bind(server_fd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr));
34 listen(server_fd, 1000);
35
36 //create epoll fd, and register the server listening fd
37 int epoll_fd = epoll_create(MAX_EPOLL_SIZE);
38 ev.events = EPOLLIN | EPOLLET;
39 ev.data.fd = server_fd;
40 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);
41
42 int active_fd_count = 1;
43 while (1)
44 {
45 //wait for some events to happen
46 int event_active_fd_count = epoll_wait(epoll_fd, events, active_fd_count, -1);
47
48 // process all events
49 for (int i = 0; i < event_active_fd_count; ++i)
50 {
51 if (events[i].data.fd == server_fd)
52 {
53 new_fd = accept(server_fd, (struct sockaddr *) &client_addr,&len);
54
55 //register new fd to epoll
56 ev.events = EPOLLIN | EPOLLET;
57 ev.data.fd = new_fd;
58 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &ev);
59 active_fd_count++;
60 }
61 else
62 {
63 handle message on events[i].data.fd
64 if (client close the connection)
65 {
66 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd,&ev);
67 active_fd_count--;
68 }
69 }
70 }
71 }
72 close(server_fd);
73 return 0;
74}

讲完epoll的常规使用方法,这里需要注意的是epoll有两种工作方式:
(1)ET:Edge Triggered,边缘触发。仅当状态发生变化时才会通知,需要细致的处理每个请求,否则容易发生丢失事件的情况。只支持非阻塞的socket。
(2)LT:Level Triggered,水平触发(默认工作方式)。只要还有没有处理的事件就会一直通知,因此不用担心事件丢失的情况。效率会低于ET触发,尤其在大并发,大流量的情况下。支持阻塞和非阻塞的socket。

最后讲讲 为什么epoll会比select高效,主要从三方面来进行论述。
(1)elect对描述符状态的改变是通过轮询来进行查找的;而epoll是当描述符状态发生改变时主动进行通知内核,这就是所谓的Reactor事件处理机制。可以用“好莱坞原则”进行描述:不要打电话给我们,我们会打电话通知你。相比之下,select的机制就好比面试结束后不停给面试官打电话询问面试结果。效率孰高孰低,可见一 斑。
(2)select的文件描述符是使用链表进行组织的;而epoll是使用红黑树这一高效数据结构组织的。
(3)select从内核到用户空间传递文件描述符上发送的信息是使用内存复制的方式进行的;而epoll是采用共享内存的方式。

转载于:https://my.oschina.net/u/581475/blog/73195

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403753.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于24点游戏的编程思路与基本算法

From: http://blog.csdn.net/wangqiulin123456/article/details/8145545 24点游戏的算法&#xff0c;其中最主要的思想就是穷举法。所谓穷举法就是列出4个数字加减乘除的各种可能性&#xff0c;包括括号的算法。我们可以将表达式分成以下几种&#xff1a;首先我们将4个数设为a…

Xtreme TaskPanel

原文来自方案网 http://www.fanganwang.com/Product-detail-item-1230.html&#xff0c;欢迎转载。 关键字&#xff1a;TaskPanel Codejock Xtreme TaskPanel为Windows开发者提供了一个非常熟悉的任务栏&#xff0c;与Windows资源管理器类似。该任务面板可以像VS.NET工具一样被…

linux设备驱动之按键外部中断

老习惯先贴一波代码再仔细分析消化。 #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #includ…

C语言实现ICMP协议Ping命令

From: http://www.360doc.com/content/12/0429/19/1317564_207540510.shtml 大部分人用ping命令只是作为查看另一个系统的网络连接是否正常的一种简单方法。在这篇文章中&#xff0c;作者将介绍如何用C语言编写一个模拟ping命令功能的程序。ping命令是用来查看网络上另一个主机…

Ubuntu 时间同步

1. 安装ntpdate工具# sudo apt-get install ntpdate2. 设置系统时间与网络时间同步# ntpdate cn.pool.ntp.org

vscode tab键快捷生成元素html标签

按照上图在设置中找到对应的文件夹&#xff0c; 直接加上"emmet.triggerExpansionOnTab": true,这段代码保存 重新打开vscode即可

Linux用ICMP协议实现简单Ping网络监测功能

From: http://www.linuxidc.com/Linux/2012-05/61073.htm ICMP是&#xff08;Internet Control Message Protocol&#xff09;Internet控制报文协议。它是TCP/IP协议族的一个子协议&#xff0c;用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路…

解决vscode格式化代码html属性换行问题; ctrl+s格式化去除分号,格式化自动单引号;解决js格式化换行问题;mac上的settings.json完整配置

右键格式化文档或者ctrl s保存 html不换行 1.安装两个插件①vetur ②Prettier - Code formatter 2.在vetur的settings.json中设置 配置ctrls触发格式化去除分号和单引号&#xff1b;配置格式化js换行&#xff1b;配置解决html属性换行 将最后一部分的设置&#xff0c;修改…

微信分享接口

看着微信分享的 demo 好纠结啊。。。不知道怎么去触发他。哪位大神可以指点一下。。。点击按钮弹出分享js不太懂。。搞了半天也没搞出来。。请教大家。wx.ready(function () {wx.onMenuShareTimeline({title: window.shareData.tTitle,link: window.shareData.timeLineLink,img…

OSI网络七层简义

OSI网络七层 1:物理层:如网卡,光纤,线览 2.数据链路层:交换机,记录MAC地址与内网IP 3.网络层:路由器,负责记录公网IP,如PPPOE拨号,固定IP 4.传输层:代理软件,如Apache代理80端口,SVN 3690端口等等 5.会话层,6.表现层是由第7层应用层决定转载于:https://blog.51cto.com/kongdq/9…

uniapp使用iconfont字体图标

vue引入字体图标看这篇 本文介绍两种方案&#xff1a;一、使用iconfont字体图标 二、使用icon图片 情景1&#xff1a;使用灰色的字体图标 方案一&#xff1a;使用iconfont字体图标 步骤1&#xff1a;下载iconfont 步骤2&#xff1a;解压后只需要将ifonfont.css这一个文件 &am…

linux中断pollselcet按键处理机制

在上一篇linux按键中断处理中&#xff0c;我们采用按键中断处理获取按键&#xff0c;在read函数中阻塞读取&#xff0c;当按键发生时&#xff0c;read自动解除阻塞&#xff0c;实现应用层读取到相应的按键值。在上一节中如果没有按键到来&#xff0c;应用层会一直阻塞等待在rea…

04:求整数的和与均值

总时间限制: 1000ms内存限制: 65536kB描述读入n&#xff08;1 < n < 10000&#xff09;个整数&#xff0c;求它们的和与均值。 输入输入第一行是一个整数n&#xff0c;表示有n个整数。第2~n1行每行包含1个整数。每个整数的绝对值均不超过10000。输出输出一行&#xff0c;…

Yeslab现任明教教主ISE课程前七部分免费发布

Yeslab现任明教教主ISE课程1-7部分免费发布 网盘&#xff1a;http://ref.so/p63jl转载于:https://blog.51cto.com/ielab/967536

socket选项: SO_REUSEADDR, SO_RCVBUF, SO_SNDBUF

From: http://blog.csdn.net/jasonliuvip/article/details/22591531 最近在看《linux高性能服务器编程》&#xff0c;在此做个日记&#xff0c;以激励自己&#xff0c;同时分享于有需要的朋友。 1. 读取和设置socket文件描述符属性&#xff1a; [cpp] view plaincopy#include …

linux 文件按照大小排列

从大往小排列 ls -lhS 从小往大排列 ls -lhSr 来源&#xff1a; http://www.shuaizhu.com/wordpress/linux%E7%B3%BB%E7%BB%9F%E4%B8%8B%EF%BC%8C%E6%8C%89%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%A7%E5%B0%8F%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E7%9A%84%E5%91%BD%E4%BB%A4…

Media所有参数汇总

Media所有参数汇总 我们最常需要用到的媒体查询器的三个特性&#xff0c;大于&#xff0c;等于&#xff0c;小于的写法。媒体查询器的全部功能肯定不止这三个功能&#xff0c;下面是我总结的它的一些参数用法解释&#xff1a; width:浏览器可视宽度。 height:浏览器可视高度。…

jni中native通过adb输出

本文主要实践了如何在jni中打印log&#xff0c;贴源码&#xff1a; Android.mk主要是巴拉的android源码中的app LOCAL_PATH : $(call my-dir) include $(CLEAR_VARS) #TARGET_PLATFORM : android-3 #LOCAL_SDK_VERSION : 19 LOCAL_MODULE : libnative LOCAL_SRC_FILES : …

[Windows]7种网络编程I/O模型代码实现实例

From: http://blog.csdn.net/woshinia/article/details/8585930 部分代码参考《[WINDOWS网络与通信程序设计].王艳平》&#xff0c;网络中一些I/O模型的代码都没有对socket是否可写做过深入研究&#xff0c;我这边会提供一些解决方法。 阻塞模式下&#xff0c;send会发生阻塞…

VScode配置eslint保存自动格式化,eslint格式化去掉分号和双引号。vscode自动保存去掉分号和双引号;““

本文是开启eslint检验和配置eslint格式化&#xff1b;如果想要关闭eslint&#xff0c;查看这篇关闭eslint方法&#xff1b; 1.必须安装的三个插件eslint&#xff0c; prettier-Code formatter &#xff0c;vetur 2.配置setting.json 3.直接将下方代码复制&#xff0c;黏…