day40——IO模型补充

server/2024/10/18 8:37:11/

2.4 epoll模型

epoll模型只有linux系统才有

epoll模型只有从linxu内核2.4版本之后才有

epoll从2.4内核到目前的4.X内核,没有更新的模型了,说明epoll模型本身已经很完美了

select的问题:

监视列表无法扩容

监视列表和返回的激活列表混在了一起

效率低下:

select需要自己管理激活的套接字

select查询哪个套接字激活了是一个双重循环,效率低下

select的内核部分,监视的套接字也是一个数组,查询哪个套接字激活了,效率也是低的

poll的问题:

效率低下:

select的内核部分,监视的套接字也是一个数组,查询哪个套接字激活了,效率也是低的

epoll彻底结局了select 和 poll的问题

epoll允许自动扩容

epoll的内核部分是以二叉树存储所有的描述符,所在查看哪个描述符激活的时候,效率很高

epoll会把所有激活的描述符,放在一个数组中,直接提供给用户,编程效率高

原型:int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
函数调用:int count = epoll_wait(fd,数组,监视的描述符的数量,-1)
功能描述:阻塞并等待监视列表中的描述符激活,并且将所有激活的描述符,放在一个数组中提供给我们
参数解析:参数 epfd:监视列表epoll要求先创建一个文件,然后将所有的要监视的描述符,写入这个文件中,并监视参数 events:用来存放所有激活的描述符的数组参数 maxevents:最大的监视描述符的数量参数 timeout:阻塞时长,单位为毫秒,0:表示不阻塞-1:表示常阻塞
返回值:激活的描述符的数量     

 epoll如何创建监视列表

原型:int epoll_create(int size);
调用:int epfd = epoll_create(想要监视的描述符数量)
功能描述:创建一个文件,该文件最多能够监视 size个字节的描述符
参数解析:参数 size:监视的描述符的最大值
返回值:返回创建出来的文件的描述符原型:int epoll_create1(int flags);
调用:int epfd = epoll_create1(EPOLL_CLOEXEC
)
功能描述:创建一个文件,用来监视描述符,该文件能够监视的描述符数量能够自动扩容
epoll如何将被监视的描述符写入文件中

 epoll如何将被监视的描述符写入文件中

原型:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
调用:epoll_ctl();
功能描述:操作监视列表,可以删除,可以添加,可以指定监视类型(监视可读,监视可写)
参数解析:参数 epfd:监视列表参数 op:具体针对监视列表的操作行为EPOLL_CTL_ADD:将参数 fd 描述符,添加进入epfd监视列表,并且由参数event决定,以何种形式进行监视EPOLL_CTL_DEL:将参数 fd 描述符,从epfd监视列表中移除,此时event参数被忽略,可以直接写NULLEPOLL_CTL_MOD:根据参数 event 更改 fd描述符的监视类型参数 fd:等待操作的描述符参数 event:一个结构体指针,结构如下struct epoll_event {uint32_t     events;      /* Epoll events */ 监视的事件类型EPOLLIN:监视描述符是否可读EPOLLOUT:监视描述符是否可写epoll_data_t data;        /* User data variable */};data 也是一个结构体,结构如下typedef union epoll_data {void        *ptr;int          fd;uint32_t     u32;uint64_t     u64;} epoll_data_t;其中关键数据是:fdepoll_event 这个结构体,在 epoll_wait的时候,传入的是这个结构体的数组我们判断哪个描述符激活,就是依靠这个fd来判断的epoll_ctl函数调用的时候,这个events.data.fd 必须和 参数 fd保持一致
#include <myhead.h>int main(int argc, const char *argv[])
{if (argc != 2){printf("请输入正确的端口号\n");return 1;}int port = atoi(argv[1]);int epfd = epoll_create1(EPOLL_CLOEXEC);if (epfd == -1){perror("epoll_create1");return 1;}int server = socket(AF_INET, SOCK_STREAM, 0);if (server == -1){perror("socket");return 1;}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr("127.0.0.1");if (bind(server, (struct sockaddr *)&addr, sizeof(addr)) == -1){perror("bind");return 1;}if (listen(server, 100) == -1){perror("listen");return 1;}struct epoll_event event;event.events = EPOLLIN;event.data.fd = server;if (epoll_ctl(epfd, EPOLL_CTL_ADD, server, &event) == -1){perror("epoll_ctl");return 1;}int fd_count = 100;struct epoll_event readfds[fd_count];while (1){int signal_count = epoll_wait(epfd, readfds, fd_count, -1);for (int i = 0; i < signal_count; i++){int fd = readfds[i].data.fd;if (fd == server){int client = accept(server, NULL, NULL);event.events = EPOLLIN;event.data.fd = client;if (epoll_ctl(epfd, EPOLL_CTL_ADD, client, &event) == -1){perror("epoll_ctl");close(client);}else{printf("有新客户端连接\n");}}else{char buf[128] = {0};int res = read(fd, buf, 128);if (res == 0){printf("有客户端断开连接\n");epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);close(fd);}else{printf("接收到客户端的消息:%s\n", buf);}}}}close(server);return 0;
}

epoll的代码模型

int epfd = epoll_create1(EPOLL_CLOEXEC)struct epoll_event event
event.events = EPOLLIN(监视类型)
event.data.fd = 想要监视的描述符
epoll_ctl(epfd,EPOLL_CTL_ADD,想要监视的描述符,&event)struct epoll_event readfds;
while(1){int signal_count = epoll_wait(epfd,readfds,监视描述符的数量,-1)for(遍历readfds){判断哪个描述符激活了{执行对应的逻辑cv            }}
}


http://www.ppmy.cn/server/104439.html

相关文章

【计算机三级-数据库技术】数据库后台编程技术

内容提要 1、掌握存储过程的定义与使用 2、掌握用户定义函数的创建与使用 3、掌握触发器的定义与使用 4、掌握游标的定义与使用 第一节 存储过程 使用T-SQL语言编写&#xff0c;有两种方式存储&#xff1a; 在客户端存储代码通过客户端程序或SQL命令向DBMS发出操作请求&…

Android笔试面试题AI答之Kotlin(16)

文章目录 74. 解释何时需要泛型类型形参约束 &#xff1f;示例 75. Kotlin reified实化类参数的原理 &#xff1f;内联函数&#xff08;Inline Functions&#xff09;类型具体化&#xff08;Type Specialization&#xff09;实化类参数&#xff08;Reified Type Parameters&…

算法5:位运算

文章目录 小试牛刀进入正题 没写代码的题&#xff0c;其链接点开都是有代码的。开始前请思考下图&#xff1a; 小试牛刀 位1的个数 class Solution { public:int hammingWeight(int n) {int res 0;while (n) {n & n - 1;res;}return res;} };比特位计数 class Solution…

git如何进行版本回退

目录 情况1&#xff1a;工作区发生改变但还未git add 情况2&#xff1a;已经git add但还未git commit 情况3&#xff1a;已经git commit但还未git push 情况4&#xff1a;已经git push 情况1&#xff1a;工作区发生改变但还未git add 情况描述&#xff1a;工作区发生变化&…

Windows Server查看W3SVC IIS服务器中对应的网站日志

W3SVC日志文件夹中序号的含义&#xff0c;格式就是W3SVC网站ID 如果没有自定义站点的日志路径&#xff0c;日志默认的路径是C:\inetpub\logs\LogFiles\ 基本上每个网站存放日志的文件夹名称都是以W3SVC开头&#xff0c;区别在于后面的ID/编号/序号&#xff0c;对应的是网站各…

自然语言处理系列三十八》词频-逆文档频率TF-IDF》Python代码实现

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列三十八Python代码实现词频-逆文档频率(TF-IDF)…

PyTorch 基础学习(13)- 混合精度训练

系列文章&#xff1a; 《PyTorch 基础学习》文章索引 基本概念 混合精度训练是深度学习中一种优化技术&#xff0c;旨在通过结合高精度&#xff08;torch.float32&#xff09;和低精度&#xff08;如 torch.float16 或 torch.bfloat16&#xff09;数据类型的优势&#xff0c;…

基于x86 平台opencv的图像采集和seetaface6的性别识别功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.2 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的性别识别功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的性别识别模块从而实现…