0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核IO多路复用之epoll简介

冬至配饺子 来源:嵌入式软件开发交流 作者:young 2022-08-08 17:53 次阅读

epoll简介

epoll是Linux内核为处理大量句柄而改进的poll,它能显著的减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

epoll的工作方式

LT(level triggered):水平触发,缺省方式,在这种方式中,内核告诉我们一个文件描述符是否就绪了,如果就绪了,就可以对描述符进行IO操作。如果不做任何操作,内核还是会继续通知。

ET(edge-triggered):边沿触发,在这种方式下,当描述符从未就绪变为就绪状态时,内核通知应用。但是如果一直不对这个描述符做IO操作,内核不会再发送通知。

区别: 边沿触发仅触发一次,水平触发会一直触发。

epoll相关函数

epoll主要有epoll_create, epoll_ctl, epoll_wait 3个系统调用。

epoll_create

int epoll_create(int size)

创建一个epoll的句柄。自从linux2.6.8之后,size参数是被忽略的。

epoll_ctl

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

epoll的事件注册函数,在这里先注册要监听的事件类型。

epfd: epoll句柄

op: 表示动作,有如下三个动作:

EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
fd: 要监听的描述符。

event: 要监听的事件,struct epoll_event结构如下:

struct epoll_event {
__uint32_t events; /* 监听的事件 */
epoll_data_t data; /* 用户数据*/
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

events可设置的值如下:

EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式
EPOLLONESHOT:只监听一次事件,当监听结束之后,要继续监听的话,需要再次加入到EPOLL队列里

epoll_wait

int epoll_wait(int epfd, structepoll_event * events, int maxevents, int timeout)
等待事件的到来。

events: 分配好的epoll_event结构体数组,epoll将会把发生的事件赋值到events数组中。

maxevents: events的大小。

timeout: 超时时间(毫秒,0会立即返回,-1将是永久阻塞)。

如果函数调用成功,返回对应I/O上已准备好的文件描述符数目,如返回0表示已超时。

使用例子


/* net_epoll.c */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define EPOLL_SIZE 10 //epoll监听的客户端的最大数目,Linux2.6.8之后该参数可以忽略
#define BUFFER_SIZE 1024

int main()
{
struct sockaddr_in server_sockaddr, client_sockaddr;
int sin_size, count;
int epfd;
struct epoll_event ev, events[EPOLL_SIZE];
int event_cnt;
int sockfd, client_fd;
char buf[BUFFER_SIZE];
//创建socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
//设置IP,端口
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY; //任意地址,也就是表示本机的所有IP
bzero(&(server_sockaddr.sin_zero), 8);
int i = 1;/* 允许重复使用本地地址与套接字进行绑定 */
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
//绑定
if (bind(sockfd, (struct sockaddr *)&server_sockaddr,
sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
//开始监听
if(listen(sockfd, MAX_QUE_CONN_NM) == -1)
{
perror("listen");
exit(1);
}

printf("listening....\n");

//创建一个epoll描述符,并将监听socket加入epoll
if((epfd = epoll_create(EPOLL_SIZE)) == -1)
{
perror("epoll_create");
exit(1);
}
else
{
ev.events = EPOLLIN | EPOLLOUT | EPOLLET; //读写事件,边沿触发
ev.data.fd = sockfd;
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
}

while(1)
{
sin_size = sizeof(struct sockaddr_in);
memset(buf, 0, sizeof(buf));
/*调用 epoll_wait()等待事件到来*/
if ((event_cnt = epoll_wait(epfd, events, EPOLL_SIZE, -1)) <= 0)
{
perror("epoll_wait");
}

for (i = 0; i < event_cnt; i++)
{
//判断来事件的是否是监听连接的socket
if (events[i].data.fd == sockfd)
{ /* 服务端接收客户端的连接请求 */
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, (socklen_t *)&sin_size))== -1)
{
perror("accept");
exit(1);
}
//将新连接的socket放进去
ev.data.fd = client_fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev);
printf("New connection from %d(socket)\n", client_fd);
}
else /* 处理从客户端发来的消息 */
{
if ((count = recv(events[i].data.fd, buf, BUFFER_SIZE, 0)) > 0)
{
printf("Received a message from %d: %s\n",
events[i].data.fd, buf);
}
else
{
close(events[i].data.fd);
ev.data.fd = events[i].data.fd;
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &ev);
printf("Client %d(socket) has left\n", events[i].data.fd);
}
}
} /* end of for fd*/
} /* end if while while*/

close(sockfd);
exit(0);
}

总结

epoll的优点是支持大数目的描述符,IO效率不随描述符数目增加而线性下降。所以在高并发网络中应用比较多,一般是在服务端。



审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10825

    浏览量

    211148
  • LINUX内核
    +关注

    关注

    1

    文章

    316

    浏览量

    21618
  • epoll
    +关注

    关注

    0

    文章

    28

    浏览量

    2947
收藏 人收藏

    评论

    相关推荐

    一节课了解IO多路复用-2021.8.31-大海老师 - 第1节 #硬声创作季

    IO多路复用
    充八万
    发布于 :2023年09月01日 21:27:46

    一节课了解IO多路复用-2021.8.31-大海老师 - 第8节 #硬声创作季

    IO多路复用
    充八万
    发布于 :2023年09月01日 21:33:38

    一节课了解IO多路复用-2021.8.31-大海老师 - 第9节 #硬声创作季

    IO多路复用
    充八万
    发布于 :2023年09月01日 21:34:29

    一节课了解IO多路复用-2021.8.31-大海老师 - 第13节 #硬声创作季

    IO多路复用
    充八万
    发布于 :2023年09月01日 21:37:50

    多路复用技术

    2.3  多路复用技术2.3.1  频分多路复用2.3.2  时分多路复用2.3.3  波分多路复用2.3.4  码分
    发表于 06-27 21:46 0次下载

    多路复用多路复用总线转换桥的设计与实现

    多路复用多路复用总线转换桥的设计与实现 提出了一种新颖的非多路复用总线与多路复用总线的转换接口电路。以两种总线的典型代表芯片TMS
    发表于 03-28 15:14 943次阅读
    非<b class='flag-5'>多路复用</b>与<b class='flag-5'>多路复用</b>总线转换桥的设计与实现

    复用器的多路复用

    复用器的多路复用  多路复用
    发表于 01-07 14:27 1184次阅读

    Linuxepoll IO多路复用机制

    epollLinux内核中的一种可扩展IO事件处理机制,最早在 Linux 2.5.44内核
    发表于 05-16 16:07 699次阅读
    <b class='flag-5'>Linux</b>中<b class='flag-5'>epoll</b> <b class='flag-5'>IO</b><b class='flag-5'>多路复用</b>机制

    深度剖析Linuxepoll机制

    Linux 系统之中有一个核心武器:epoll 池,在高并发的,高吞吐的 IO 系统中常常见到 epoll 的身影。 IO
    的头像 发表于 07-29 10:52 1393次阅读

    网络IO的弊端以及多路复用IO的优势

    为了讲多路复用,当然还是要跟风,采用鞭尸的思路,先讲讲传统的网络 IO 的弊端,用拉踩的方式捧起多路复用 IO 的优势。 为了方便理解,以下所有代码都是伪代码,知道其表达的意思即可。
    的头像 发表于 08-25 18:01 2867次阅读
    网络<b class='flag-5'>IO</b>的弊端以及<b class='flag-5'>多路复用</b><b class='flag-5'>IO</b>的优势

    linux异步io框架iouring应用

    完善的异步IO(网络IO、磁盘IO)机制。 在网络编程中,我们通常使用epoll IO多路复用
    的头像 发表于 11-08 15:39 646次阅读
    <b class='flag-5'>linux</b>异步<b class='flag-5'>io</b>框架iouring应用

    epoll来实现多路复用

    本人用epoll来实现多路复用epoll触发模式有两种: ET(边缘模式) LT(水平模式) LT模式 是标准模式,意味着每次epoll_wait()返回后,事件处理后,如果之后还有
    的头像 发表于 11-09 10:15 485次阅读
    用<b class='flag-5'>epoll</b>来实现<b class='flag-5'>多路复用</b>

    IO多路复用基本概念

    一、IO多路复用基本概念 select、poll、epoll都是IO多路复用的机制。IO
    的头像 发表于 11-10 16:34 1360次阅读
    <b class='flag-5'>IO</b><b class='flag-5'>多路复用</b>基本概念

    什么是io多路复用IO多路复用的优缺点

    IO多路复用是一种同步IO模型,它允许单个进程/线程同时处理多个IO请求。具体来说,一个进程/线程可以监视多个文件句柄,一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作。在没
    的头像 发表于 01-18 15:48 1591次阅读

    Linux--IO多路复用(select,poll,epoll)

    :等待数据到达:程序等待数据从IO设备传输到内核空间。在这个阶段,IO多路复用的系统调用会阻塞,直到至少有一个描述符准备好进行IO操作。数据
    的头像 发表于 11-06 16:13 159次阅读