epoll分析

linux内核中的poll机制实现原理 下面是函数调用情况: SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,         long, timeout_msecs)          #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) #d... 阅读详情

ep_insert这个函数开始分析 里面调用了

init_poll_funcptr(&epq.pt,ep_ptable_queue_proc);

init_poll_funcptr这个函数就一句

static inline voidinit_poll_funcptr(poll_table *pt, poll_queue_proc qproc)

{

         pt->qproc= qproc;

}

也就是将ep_ptable_queue_proc这个函数指针赋值给(&epq.pt)->qproc

revents = tfile->f_op->poll(tfile,&epq.pt);将调用pipe_poll(以pipe为例)

pipe_poll(struct file *filp, poll_table*wait)里面有poll_wait(filp, &pipe->wait, wait);这一句

poll_wait里面

static inline void poll_wait(struct file *filp, wait_queue_head_t * wait_address, poll_table *p)

{

         if(p && wait_address)

                   p->qproc(filp,wait_address, p);  #1

}

参数p就是之前epoll里的&epq.pt,p->qproc也就是ep_ptable_queue_proc

第二个参数wait_address就是&pipe->wait,这个pipe的wait是什么呢我们可以看一下

struct pipe_inode_info *alloc_pipe_info(struct inode *inode)

{

         structpipe_inode_info *pipe;

 

         pipe= kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);

         if(pipe) {

                   init_waitqueue_head(&pipe->wait);

                   pipe->r_counter= pipe->w_counter = 1;

                   pipe->inode= inode;

         }

 

         returnpipe;

}

init_waitqueue_head该函数初始化一个已经存在的等待队列头,它将整个队列设置为"未上锁"状态,并将链表指针prev和next指向它自身。也就是初始化&pipe->wait这个等待队列头的指针。

我们再回过头来看#1这个地方,也就变成了ep_ptable_queue_proc(filp, &pipe->wait, &epq.pt)

 

static void ep_ptable_queue_proc(structfile *file, wait_queue_head_t *whead,

                                      poll_table *pt)

{

         structepitem *epi = ep_item_from_epqueue(pt);

         structeppoll_entry *pwq;

 

         if(epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache,GFP_KERNEL))) {

                   init_waitqueue_func_entry(&pwq->wait,ep_poll_callback);

                   pwq->whead= whead;

                   pwq->base= epi;

                   add_wait_queue(whead,&pwq->wait);

                   list_add_tail(&pwq->llink,&epi->pwqlist);

                   epi->nwait++;

         }else {

                   /*We have to signal that an error occurred */

                   epi->nwait= -1;

         }

}

struct epitem *epi =ep_item_from_epqueue(pt);是通过&epq.pt找到其从属的epitem对象。

pwq = kmem_cache_alloc(pwq_cache,GFP_KERNEL)); alloc一个

/* Wait structure used by the poll hooks */

struct eppoll_entry {

         /*List header used to link this structure to the "struct epitem" */

         structlist_head llink;

 

         /*The "base" pointer is set to the container "struct epitem"*/

         void*base;

 

         /*

          * Wait queue item that will be linked to thetarget file wait

          * queue head.

          */

         wait_queue_twait;

 

         /*The wait queue head that linked the "wait" wait queue item */

         wait_queue_head_t*whead;

};

init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);将回调函数ep_poll_callback注册给了&pwq->wait(等待项,这个等待项会被连入到pipe等待队列中)的func项,当

&pipe->wait 被赋值给了pwq->whead

add_wait_queue(whead, &pwq->wait);将等待项连接到&pipe->wait等待队列头中

 

至此pipe_poll完成了

pipe_write的时候会wake_up_interruptible_sync(&pipe->wait);调用关系如下

wake_up_interruptible_sync(&pipe->wait);

->__wake_up_sync((x),TASK_INTERRUPTIBLE,1)

         ->__wake_up_sync(wait_queue_head_t*q, unsigned int mode, int nr_exclusive)

                   ->__wake_up_common(q,mode, nr_exclusive, sync, NULL);

static void__wake_up_common(wait_queue_head_t *q, unsigned int mode,

                                 int nr_exclusive, int sync, void *key)

{

         wait_queue_t *curr, *next;

         list_for_each_entry_safe(curr, next,&q->task_list, task_list) {

                   unsigned flags =curr->flags;

 

                   if (curr->func(curr, mode,sync, key) &&

                                     (flags& WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)

                            break;

         }

}

这个curr->func就是之前的&pwq->wait 的func也就是ep_poll_callback,他依次调用pipe等待队列上的各个等待项对应的callback函数

回调函数在调用时会再执行pipe_poll函数,来明确是不是指定的关注事件发生,若成立则将 epitem插入到eventpoll中的rdlist,并激活在epoll fd上wait的进程,并将事件回传至用户态.这样就能实现对目标fd的事件监听.(to be continued…)

Linux epoll模型详解及源码分析 一、epoll简介 epoll是当前在Linux下开发大规模并发网络程序的热门选择,epoll在Linux2.6内核中正式引入,和select相似,都是IO多路复用(IO multiplexing)技术。 按照man手册的说法,epoll是为处理大批量句柄而做了改进的poll。 Linux下有以下几个经典的服务器模型: 1、PPC模型和TPC模型 PPC(Process Per Co... 阅读详情

相关推荐

epoll源码分析

码字不易,转载请标明出处 前言 Linux内核提供了3个关键函数供用户来操作epoll,分别是: epoll_create(), 创建eventpoll对象 epoll_ctl(), 操作eventpoll对象 epoll_wait(), 从eventpoll对象中返回活跃的事件 而操作系统内部会用到一个名叫epoll_event_callback()的回调函数来调度epoll对...

Replus_的博客 965

内核poll回调和等待队列

poll的本意是调查,在程序里就是检查事件是否发生。f_op→poll() 是文件系统的统一IO检测函数。poll_wait() 函数,把当前进程加入到驱动里自定义的等待队列上,当驱动事件就绪后,就可以在驱动里自定义的等待队列上唤醒调用poll的进程。设置回调函数,一般回调函数func是内核默认函数 default_wake_function,可以自己设置,功能就是唤醒了进程。epoll就利用了队列钩子函数把产生的事件内容copy到rdlist ,这样就不需要我们自己遍历监听句柄们查有谁产生了事件。

tang063的专栏 1140

linux epoll 源码分析

本文章源码基于kernel 5.5版本,主要分析epoll在kernel的实现原理,主要源码在 kernel/fs/eventpoll.c。 一,关键结构体 关键结构体主要有以下2个需要留意,里边包含的成员用来干嘛同学们看代码应该看得懂,在此只是简单提一下。 struct eventpoll ,struct epitem,这边需要留意的主要就这2个结构体,eventpoll每个进程调e...

goodnight1994的博客 1035

字符设备驱动之poll机制

poll 机制分析 所有的系统调用,基于都可以在它的名字前加上“sys_”前缀,这就是它在内核中对应 的函数。比如系统调用 open、read、write、poll,与之对应的内核函数为:sys_open、sys_read、 sys_write、sys_poll。 一、内核框架: 对于系统调用 poll 或 select,它们对应的内核函数都是 sys_poll。分析 sys_poll,即可理解 ...

qq_42230338的博客 565

epoll源代码分析

文章目录epoll_filefdlist_headepoll_event红黑树的节点epitemeventpolleppoll_entry epoll_filefd struct epoll_filefd { struct file *file; int fd; }; list_head struct list_head { struct list_head *next, *prev; }; epoll_event struct epoll_event { __u32 events; __u6

qq_36553387的博客 883

linux epoll实现分析

epoll的作用是进行I/O的多路复用,可以同时监听多个fd产生的事件。常结合异步处理实现单线程的高并发。在多核环境中,可以结合多线程实现负载分担。 本文主要分析一下linux epoll的实现。 API epoll_create(int size);. epoll_create1(int flags); 创建一个epoll实例,并返回与之关联的一个fd.这是后面我们继续使用epoll其...

happyAnger6的专栏 707

嵌入式Linux驱动学习 —— poll机制

1 IO模式 Linux下的五种IO模型: 1)阻塞IO(blocking IO):读数据,若没有,一直阻塞,直到有数据后返回; 2)非阻塞IO (nonblocking IO):读数据,不管有没有,直接返回; 3)IO复用(select 和poll) (IO multiplexing):同时监听多路数据,只要有一路有数据或超时返回; 4)信号驱动IO (signal driven IO (SIGIO)):很少用; 5)异步IO (asynchronous IO (the POSIX aio_functio

chen06130的博客 374

GD32F470 DSP库移植避坑指南:从CMSIS版本冲突到AC6工程配置

本文详细解析了在GD32F470平台上移植CMSIS-DSP库的完整流程与关键避坑点。针对CMSIS版本冲突、AC6编译器下的浮点ABI配置、DSP库源文件添加等核心难题,提供了经过验证的解决方案,帮助开发者高效完成移植,确保硬件FPU正常工作并优化性能。

data3的博客 530

Linux中poll机制的理解

首先分析下应用程序的执行过程: int main(int argc, char **argv) {  int fd;  unsigned char key_val;  int ret;  struct pollfd fds[1];    fd = open("/dev/buttons", O_RDWR);  if (fd  {   printf("can't open!

kerwins的机器学习之路 3114

用宝塔面板+CentOS 7.6,30分钟搞定DNF手游私服搭建(附全套资源下载)

本文详细介绍了如何使用宝塔面板和CentOS 7.6在30分钟内快速搭建DNF手游私服。通过图形化界面操作,无需复杂命令,即可完成服务端部署、MySQL数据库配置及客户端适配,适合Linux新手快速上手。

weixin_33737774的博客 598

ARM架构下Horizon Client安装全攻略:从依赖检查到环境变量配置

本文详细介绍了在ARM架构设备上安装VMware Horizon Client的全过程,包括依赖检查、软件包获取、系统部署和环境变量配置。特别针对华为鲲鹏等ARM平台,提供了从基础准备到性能优化的完整指南,帮助用户高效完成虚拟桌面客户端的部署与调优。

github5actions的博客 551

poll和epoll原理对比、分析

随着2.6内核对epoll的完全支持,网络上很多的文章和示例代码都提供了这样一个信息:使用epoll代替传统的poll能给网络服务应用带来性能上的提升。但大多文章里关于性能提升的原因解释的较少,这里我将试分析一下内核(2.6.21.1)代码中poll与epoll的工作原理,然后再通过一些测试数据来对比具体效果。         POLL:        先说poll,poll或select为大

woxiaozhi的专栏 1687

ESP32+ST7789 LCD屏实战:5分钟搞定中文显示与图片渲染(附完整代码)

本文提供了一份详细的ESP32驱动ST7789 LCD屏幕的实战指南。通过清晰的SPI硬件连接说明、ESP-IDF框架下的初始化代码,以及图片渲染与中文字库构建的核心算法,帮助开发者快速实现中文显示与图片渲染功能,并附有完整的代码示例和性能优化技巧。

weixin_29189377的博客 437

Linux内核学习之 -- epoll()一族系统调用分析笔记

linux 4.19epoll()也是一种I/O多路复用的技术,但是完全不同于select()/poll()。更加高效,高效的原因其他博客也都提到了,这篇笔记主要是从源码的角度来分析一下实现过程。作为自己的学习笔记,分析都在代码注释中,后续回顾的时候看注释好一点。对于epoll()的分析建立在《Linux内核学习之 – 系统调用open()和write()的实现笔记》 + 《Linux内核学习之 – 系统调用poll()分析笔记》的基础上,因为有很多通用的步骤和环节。

xi_xix_i的博客 1417

使用Python,OpenCV查找图像中的最亮点

这篇博客展示了,为什么在图像中找到最亮的点之前应用高斯模糊是至关重要的。 通过应用高斯模糊,可以将每个给定半径内的像素平均在一起。取平均值可以去除高频噪声,否则会影响cv2.minMaxLoc函数的结果。 一定要研究高斯模糊半径的恰当值。如果取值太小,将会减轻平均值的影响,而忽略了更大、更亮的区域。但是如果半径太大,将无法探测到小的明亮区域。

qq_40985985的博客 3809

LVGL 拨盘菜单(Dial Menu)

h。

摸鱼专家 191

epoll原理以及系统调用案例分析

一、epoll原理一、epoll原理二、epoll系统调用使用c库封装的3个epoll系统调用,具体源码如下:此系统调用对文件描述符epfd引用的epoll实例执行控制操作,它要求操作op对目标文件描述符fd执行。op参数有效值为:EPOLL_CTL_ADD/EPOLL_CTL_MOD/EPOLL_CTL_DEL.等待 epoll 文件描述符上的 I/O 事件。epfd 引用的 epoll 实例上的事件,事件所指向的存储区域将包含供调用者使用的事件。

m0_74186706的博客 1429

【ESP 保姆级教程】玩转emqx数据集成篇④ ——数据桥接之HTTP服务

主要是学习数据桥接功能以及构建自己的http服务器,这是一个非常有用的功能。包括各种传感器上报基本上都需要数据桥接功能支持,所以还是希望认真学习这一块开发,然后结合数据库存储等等知识点进行进一步学习。

单片机菜鸟哥的博客 1306

图文并茂的epoll机制全面分析

文章目录epollepoll机制概述相关接口epoll技术细节内核态的主流程相关数据结构总览事件的注册与处理谈一谈file_operations中的poll回调与poll_waitepoll_wait监听与被唤醒的流程多核环境下,多个事件同时到达的情况多核环境下,不及时调用epoll_wait,导致事件积累的情况epoll LT/ET 模式一个关于LT模式的问题epoll 惊群问题关于惊群对于nginx,多个进程分别创建自己的epfd的情形对于多个进程共用同一个epfd的情形为什么IO多路复用机制需要搭配非

x727847140的博客 2589

apollo-慢速车向左绕行

当主车前方出现其他车辆时,通过左侧车道对前车绕行。

是菜鸟o的博客 309

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SylixOS 之epoll异常分析

1. SylixOS epoll介绍 SylixOS为了兼容Linux的epoll,创建了epoll的兼容子系统,并支持了epoll的部分功能。SylixOS epoll兼容子系统是由select子系统模拟出来的,所以效率没有select高。 2. epoll异常分析 2....

chudian1163的博客 240

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

poll epoll 分析

<br />随着2.6内核对epoll的完全支持,网络上很多的文章和示例代码都提供了这样一个信息:使用epoll代替传统的poll能给网络服务应用带来性能上<br />的提升。但大多文章里关于性能提升的原因解释的较少,这里我将试分析一下内核(2.6.21.1)代码中poll与epoll的工作原理,然后再通过一些<br />测试数据来对比具体效果。<br />        POLL:<br />       先说poll,poll或select为大部分Unix/Linux程序员所熟悉,这俩个东西原理类似,性

Programer From Scrach 619

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Epoll详解及源码分析

epoll是当前在Linux下开发大规模并发网络程序的热门人选,epoll 在Linux2.6内核中正式引入,和select相似,都是I/O多路复用(IO multiplexing)技术,按照man手册的说法:是为处理大批量句柄而作了改进的poll。 Linux下有以下几个经典的服务器模型:   ①Apache模型(Process Per Connection,简称PPC)

kingkongkang的博客 944
上一篇: 乱谈服务器编程
下一篇: 基数(radix)树
linuxcc2011
博客等级 码龄16年 2粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值