linux2.6.9 epoll系统调用源码分析

合集下载

linux下ecall用法

linux下ecall用法

linux下ecall用法
在Linux下,ecall是用于执行系统调用的一种机制。

系统调用是操作系统提供给应用程序的接口,用于访问操作系统内核提供的服务。

通过ecall,应用程序可以调用系统调用并与之交互。

在Linux中,ecall的使用通常涉及到以下几个步骤:
1.包含头文件:在程序中包含必要的头文件,以便使用ecall机制。

通常情况下,需要包含<sys/syscall.h>头文件。

2.定义系统调用号:在程序中定义系统调用的编号。

系统调用号是一个整数值,用于标识特定的系统调用。

可以在头文件中找到系统调用号的定义。

3.调用ecall函数:在程序中使用ecall函数来执行系统调用。

ecall函数的原型如下:
long ecall(long num, long arg1, long arg2, long arg3, long arg4, long arg5);
其中,num参数指定要执行的系统调用编号,其他参数是传递给系统调用的参数。

4.处理返回值:ecall函数将返回系统调用的结果。

根据不同的系统调用,返回值的意义可能不同。

可以通过检查返回值来处理系统调用的结果。

需要注意的是,ecall函数是低级函数,通常用于与内核交互。

在实际的应用程序开发中,更常用的是高级的系统调用接口,如open(), read(), write(), close()等函数。

这些函数提供了更高级别的抽象,使得程序更加易于使用和管理。

poll用法linux

poll用法linux

poll用法linux
在Linux中,"poll"是一个系统调用,用于监视多个文件描述
符的状态,以确定是否可以从它们中的任何一个读取或写入数据而
不会被阻塞。

这个系统调用通常用于编写高效的I/O多路复用程序,可以在网络编程和服务器编程中发挥重要作用。

"poll"系统调用的基本语法如下:
c.
#include <poll.h>。

int poll(struct pollfd fds, nfds_t nfds, int timeout);
其中,fds是一个指向struct pollfd结构的指针,用于指定
要监视的文件描述符及其所关注的事件;nfds是要监视的文件描述
符的数量;timeout是超时时间,指定poll调用在阻塞之前要等待
的毫秒数。

成功时,poll会返回就绪的文件描述符的数量,超时时
返回0,出错时返回-1。

在使用poll时,需要注意以下几点:
1. 需要对fds数组中的每个文件描述符进行正确的初始化,设置关注的事件类型和初始状态。

2. 可以使用宏来设置关注的事件类型,如POLLIN(可读事件)、POLLOUT(可写事件)等。

3. 使用超时参数可以避免poll调用永久阻塞,可以在一定时间内轮询文件描述符的状态。

除了基本的使用方法外,还可以从性能、并发性、错误处理等角度对poll系统调用进行深入讨论。

在实际编程中,需要根据具体的应用场景和需求来灵活运用poll系统调用,以实现高效的I/O多路复用。

c语言epoll详解

c语言epoll详解

c语言epoll详解摘要:1.简介- 什么是C 语言epoll- epoll 的优势2.epoll 原理- epoll 的工作机制- epoll 的事件处理3.epoll 的使用- 安装epoll 模块- 创建epoll 实例- 添加、修改、删除事件- 查询事件- 处理事件4.epoll 的例子- 简单的epoll 例子- 更复杂的epoll 例子5.epoll 的应用场景- 网络编程- 服务器开发正文:C 语言epoll 详解C语言epoll是一种高效的I/O事件处理机制,相较于传统的select和poll,epoll在性能上有很大的优势,因此被广泛应用于网络编程和服务器开发等领域。

1.简介epoll是Linux下的一种I/O事件处理机制,它能够实现对大量I/O进行监控,只有发生变化的I/O才会通知用户进程。

这使得用户进程可以更加高效地处理I/O事件,避免了不必要的上下文切换和资源浪费。

2.epoll 原理epoll 的工作机制类似于一个事件驱动的系统。

它包含一个内核模块和一个用户进程。

内核模块负责管理I/O 资源,用户进程通过epoll_create、epoll_ctl 等系统调用与内核模块进行交互,实现对I/O 资源的监控和事件处理。

当用户进程调用epoll_wait 时,内核模块会遍历所有注册的I/O 资源,检查它们的状态是否发生变化。

如果某个I/O 资源的状态发生了变化,内核模块就会将这个变化通知给用户进程。

用户进程可以根据收到的通知来执行相应的操作。

3.epoll 的使用要在C 语言中使用epoll,首先需要安装epoll 模块。

安装方法如下:```#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("An epoll module");module_init(epoll_init);module_exit(epoll_exit);```接下来,可以创建epoll 实例、添加、修改、删除事件以及查询事件。

Linux内核中系统调用详解

Linux内核中系统调用详解

Linux内核中系统调用详解什么是系统调用?(Linux)内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。

用户可以通过系统调用命令在自己的应用程序中调用它们。

从某种角度来看,系统调用和普通的函数调用非常相似。

区别仅仅在于,系统调用由(操作系统)核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

随Linux核心还提供了一些(C语言)函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。

为什么要用系统调用?实际上,很多已经被我们习以为常的C语言标准函数,在Linux 平台上的实现都是靠系统调用完成的,所以如果想对系统底层的原理作深入的了解,掌握各种系统调用是初步的要求。

进一步,若想成为一名Linux下(编程)高手,也就是我们常说的Hacker,其标志之一也是能对各种系统调用有透彻的了解。

即使除去上面的原因,在平常的编程中你也会发现,在很多情况下,系统调用是实现你的想法的简洁有效的途径,所以有可能的话应该尽量多掌握一些系统调用,这会对你的程序设计过程带来意想不到的帮助。

系统调用是怎么工作的?一般的,进程是不能访问内核的。

它不能访问内核所占内存空间也不能调用内核函数。

(CPU)(硬件)决定了这些(这就是为什么它被称作"保护模式")。

系统调用是这些规则的一个例外。

其原理是进程先用适当的值填充(寄存器),然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。

在(Intel)CPU中,这个由中断0x80实现。

硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统的内核--所以你就可以为所欲为。

进程可以跳转到的内核位置叫做sysem_call。

这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。

然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。

linux统计 的文件 eventpoll 内容-概述说明以及解释

linux统计 的文件 eventpoll 内容-概述说明以及解释

linux统计的文件eventpoll 内容-概述说明以及解释1.引言1.1 概述引言部分的概述内容可以包括:- Linux系统中的事件驱动机制在处理文件输入输出和网络通信等方面起着至关重要的作用。

- eventpoll是Linux系统中一种高效的事件驱动机制,能够实现对文件描述符状态变化的监控和处理。

- 本文将深入探讨eventpoll的原理、使用方法以及其在系统中的重要性。

概述部分的内容应该简明扼要地介绍本文将要探讨的主题,引起读者的兴趣,让读者对文章的内容有一个初步的了解。

1.2文章结构1.2 文章结构本文将首先对eventpoll进行简要介绍,包括其概念、用途和特点。

随后将详细讨论eventpoll的使用方法,包括如何在Linux系统中进行操作和配置。

接着将深入探讨eventpoll的实现原理,包括其底层机制和算法。

最后,通过总结eventpoll在Linux系统中的重要性,展望其未来的发展,并以一段温馨的结束语来结束整篇文章。

通过这样的结构安排,读者将能够全面了解eventpoll的相关知识,从而更好地理解和应用这一功能。

1.3 目的本文旨在深入了解Linux系统中的文件eventpoll,探讨其在系统中的重要性和应用。

通过对eventpoll的简介、使用和实现原理的分析,希望能够帮助读者更全面地理解eventpoll在Linux系统中的作用和功能,以及其所带来的好处。

同时,也旨在为未来eventpoll的发展提供一些思路和展望,促进Linux系统在事件处理机制上的进一步完善和优化。

通过本文的阐述,希望读者能对Linux中的eventpoll有一个更深入的认识,进而为他们在实际应用中的决策和操作提供一定的参考和帮助。

2.正文2.1 eventpoll简介eventpoll是Linux内核中一个用于事件通知和事件等待的机制。

它通过一个轻量级的数据结构和系统调用接口,实现了高效的事件处理和等待机制。

linux epoll 实例

linux epoll 实例

linux epoll 实例epoll是Linux内核为处理大批量文件描述符而作了改进的poll(2),是LINUX下多路复用IO支持的一种机制,它基于事件驱动模型,用户把要发生的事件(就是文件描述符)放入内核的一个poll结构,文件描述符就放在一个数组中,每当一个有效I/O发生,加入到内核队列中,放到用户定义的epoll结构中,这个新发生的事件将立即传送给用户进程,在该进程的某一线程中,使用epoll_Wait()函数等待事件的发生,等待到发生的事件时,epoll会将发生的事件告诉用户程序,比如连接,数据可读等。

epoll的优势:1、内核利用epoll的重新把文件描述符放入有序的数据结构,比poll管理更为高效,更少的遍历处理全部的文件描述符;2、epoll模型支持IO多路复用,同时可以监听到数以千计的fd;3、epoll提供水平触发和边沿触发两种模式;4、epoll支持ET和LT两种类型;5、epoll实现轮询式监视,提升系统性能,使用更轻松和实时;在Linux中使用epoll时,首先need to initilize一个epoll实例,而epoll_create函数来完成这一初始化(epoll_create()的参数是数据要放入epoll的最大句柄数),epoll_create()返回的文件描述符(int类型),被用于后续的epoll操作;然后用epoll_ctl()来添加文件描述符至内核的epoll表头,最后,进程通过调用epoll_wait()来等待某个文件描述符因某种事件发生而Entry Ready状态,epoll_wait()阻塞等待,epoll函数会返回可以操作的文件描述符列表。

epoll能处理上千个fd事件不错过,但是也有其缺点,它不能实现即时通讯,新连接的处理是有延迟的,而且,如果epoll_wait()中断,它会只返回一个已就绪的fd,而不检查其它的fd.综上所述,epoll是LINUX下高效的多路复用IO编程的机制,它能处理上千个fd事件,用在Server开发中是一种正确选择,相对于select/poll很大提高了处理效率,且支持水平触发和边沿触发两种模式,也支持ET和LT两种类型。

poll函数详解以及实例分析

poll函数详解以及实例分析

poll函数详解以及实例分析1、基本知识 poll的机制与select类似,与select在本质上没有多⼤差别,管理多个描述符也是进⾏轮询,根据描述符的状态进⾏处理,但是poll没有最⼤⽂件描述符数量的限制。

poll和select同样存在⼀个缺点就是,包含⼤量⽂件描述符的数组被整体复制于⽤户态和内核的地址空间之间,⽽不论这些⽂件描述符是否就绪,它的开销随着⽂件描述符数量的增加⽽线性增⼤。

2、poll函数 函数格式如下所⽰:# include <poll.h>int poll ( struct pollfd * fds, unsigned int nfds, int timeout);pollfd结构体定义如下:struct pollfd {int fd; /* ⽂件描述符 */short events; /* 等待的事件 */short revents; /* 实际发⽣了的事件 */} ; 每⼀个pollfd结构体指定了⼀个被监视的⽂件描述符,可以传递多个结构体,指⽰poll()监视多个⽂件描述符。

每个结构体的events域是监视该⽂件描述符的事件掩码,由⽤户来设置这个域。

revents域是⽂件描述符的操作结果事件掩码,内核在调⽤返回时设置这个域。

events 域中请求的任何事件都可能在revents域中返回。

合法的事件如下: POLLIN 有数据可读。

POLLRDNORM 有普通数据可读。

POLLRDBAND 有优先数据可读。

POLLPRI 有紧迫数据可读。

POLLOUT 写数据不会导致阻塞。

POLLWRNORM 写普通数据不会导致阻塞。

POLLWRBAND 写优先数据不会导致阻塞。

POLLMSGSIGPOLL 消息可⽤。

此外,revents域中还可能返回下列事件: POLLER 指定的⽂件描述符发⽣错误。

POLLHUP 指定的⽂件描述符挂起事件。

POLLNVAL 指定的⽂件描述符⾮法。

linux中select、poll、epoll原理

linux中select、poll、epoll原理

linux中select、poll、epoll原理select、poll和epoll是Linux下常用的I/O多路复用技术,都用于实现高效的事件驱动型的网络编程。

1. select(选择)select是最古老的I/O多路复用机制,它通过在套接字上设置阻塞(阻塞方式)进行等待,一旦有文件描述符准备就绪(可读、可写等),则返回。

select使用fd_set集合来保存要监听的文件描述符,因此其监听的文件描述符数量受到系统给定的FD_SETSIZE限制。

select的实现原理是:在内核中创建一个称为“等待队列”的数据结构(fd_set),该队列保存了需要等待的文件描述符,当某个文件描述符就绪时,会通过和用户进程的映射表通知用户进程。

select通过轮询所有注册的文件描述符,检查哪些文件描述符已经准备好,并将准备好的文件描述符从用户态拷贝到内核态。

select的缺点是每次调用都需要轮询全部的注册文件描述符,效率较低。

2. poll(轮询)poll是在select的基础上进行改进的多路复用技术。

poll与select的最大区别在于,它没有限制文件描述符的数量,并且使用了一个pollfd结构体数组来保存每个文件描述符及其关注的事件。

poll在内核中创建一个称为“等待队列”的数据结构,该队列保存了需要等待的文件描述符,当某个文件描述符就绪时,会通过和用户进程的映射表通知用户进程。

poll的实现原理是:将用户进程注册要监听的文件描述符及其关注的事件存储在内核中的一个事件表中,当发生事件时,内核会将该事件存储在内核态的事件表中,并通知用户进程。

与select不同的是,poll只需在事件发生时拷贝某些信息到内核态,而不需要拷贝全部的文件描述符。

poll的缺点是,当注册的文件描述符数量较大时,每次调用poll都需要遍历整个事件表,效率较低。

3. epoll(事件通知)epoll是Linux特有的一种I/O多路复用机制,通过内核与用户空间的共享内存来实现高效的事件通知。

p o l l 方 法 的 基 本 概 念

p o l l 方 法 的 基 本 概 念

详细说说select poll epoll(以下内容来自网络和自己的总结,再次感谢网络中的大神们提供的见解)在探索select poll? epoll之前我们首先要知道什么叫多路复用:下来探索一下为什么会用到多路复用:首先我们看看一个客户端请求服务器的完整过程。

首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据。

具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,你再继续吧。

阻塞调用会进入内核等待,cpu就会让出去给其他进程使用了,你可能会说那么加进程数呀,当读写事件十分多的时候会创建很多的进程,此时进程的上下文切换会占用过多的cpu资-源。

有人会说那么用线程,其实线程的上下文切换也会占用过多资-源,而且还会引入线程之间同步和互斥的问题,因为线程之间看到的是同一块内存资-源。

所以我么就会思考能不能用一个进程来查看很多的IO事件,比如每一个人都在钓鱼每一个鱼上钩都比做是一个事件发生的话,那么一百个事件发生你可以让一百个人在那里一人拿一个鱼竿进行钓鱼,你自己负责进行鱼的收集。

此时如果没有鱼上钩,那一百个人就在那阻塞等待,你自己为了收鱼也在空闲着。

这里的你自己可以比作CPU,一般个人可以比作多个进程,此时如果不是所有鱼都上钩,你就十分空闲其他人也在那拿着鱼竿空闲等待着,如果同时有多个鱼上钩了,多个人会像你汇报,此时汇报的顺序问题就是形成混乱。

此时我们可以进行一下改进,比如专门找一个人拿着许多鱼竿,当一个鱼竿上的鱼上钩以后再拉起鱼竿,这样节约了人力,还解决了问题。

下来讲一个真实的故事吧:假设你是一个机场的空管,你需要管理到你机场的所有的航线,包括进港,出港,有些航班需要放到停机坪等待,有些航班需要去登机口接乘客。

你会怎么做?最简单的做法,就是你去招一大批空管员,然后每人盯一架飞机,从进港,接客,排位,出港,航线监控,直至交接给下一个空港,全程监控。

linux中select、poll、epoll原理详解

linux中select、poll、epoll原理详解

linux中select、poll、epoll原理详解目录1. 引言1.1 背景和意义1.2 结构概述1.3 目的2. select原理详解2.1 基本概念2.2 使用方法2.3 应用场景3. poll原理详解3.1 基本概念3.2 使用方法3.3 应用场景4. epoll原理详解4.1 基本概念4.2 使用方法4.3 应用场景5. 结论5.1 对比分析选择合适的IO多路复用器5.2 总结与展望引言1.1 背景和意义在计算机网络编程中,同时监听多个文件描述符的可读、可写和异常事件是一项基本任务。

为了高效地处理这些事件,Linux提供了三种IO多路复用器:select、poll和epoll。

它们允许程序通过一次系统调用就能同时监听多个文件描述符,并在有可读、可写或异常事件发生时进行相应的处理。

使用IO多路复用器可以避免使用阻塞式IO或者轮询方式造成的性能损失,提高了程序的效率和响应速度。

尤其对于具有大量并发连接的服务器程序来说,选择合适的IO多路复用器可以极大地提升系统性能。

1.2 结构概述本文将详细解析Linux中三种IO多路复用器的原理和使用方法,包括select、poll和epoll。

对于每种IO多路复用器,我们将介绍其基本概念、使用方法以及适用场景。

通过深入理解这些IO多路复用器的工作原理,我们可以更好地掌握它们的特点及优缺点,并根据实际需求选择合适的方式来进行网络编程。

1.3 目的本文旨在帮助读者全面了解Linux中select、poll和epoll的原理和使用方法,以及它们在网络编程中的应用场景。

在深入理解这些IO多路复用器的基础上,读者可以根据实际需求灵活选择合适的IO多路复用器,提升程序的性能和可扩展性。

在接下来的文章中,我们将逐一介绍select、poll和epoll的原理详解、使用方法和应用场景,并进行对比分析,最后总结归纳各种IO多路复用器的特点及适用情况。

2. select原理详解2.1 基本概念在Linux系统中,select是一种常用的I/O多路复用机制,它可以监视多个文件描述符的状态是否满足某种条件,在有一或多个文件描述符就绪时通知进程进行相应的 I/O操作。

Linux 源代码分析

Linux 源代码分析

Linux内核(2.6.13.2)源代码分析苗彦超摘要:1系统启动1.1汇编代码head.S及以前设置CPU状态初值,创建进程0,建立进程堆栈:movq init_rsp(%rip), %rsp,init_rsp定义.globl init_rspinit_rsp:.quad init_thread_union+THREAD_SIZE-8即将虚地址init_thread_union+THREAD_SIZE-8作为当前进程(进程0)核心空间堆栈栈底,init_thread_union定义于文件arch/x86_64/kernel/init_task.c中:union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) ={INIT_THREAD_INFO(init_task)};INIT_THREAD_INFO定义于文件include/asm-x86_64/thread_info.h中,初始化init_thread_union.task = &init_task,init_task同样定义于文件init_task.c中,初始化为:struct task_struct init_task = INIT_TASK(init_task);INIT_TASK宏在include/linux/init_task.h中定义。

全部利用编译时静态设置的初值,将进程0的控制结构设置完成,使进程0可以按普通核心进程访问。

init_task.mm = NULL; init_task.active_mm = INIT_MM(init_mm), init_m = “swapper”INIT_MM将init_mm.pgd初始化为swapper_pg_dir,即init_level4_pgt,定义与head.S中。

c语言epoll详解

c语言epoll详解

c语言epoll详解摘要:1.简介- 什么是C 语言epoll- epoll 的作用- epoll 与select、poll 的关系2.epoll 的工作原理- epoll 的事件驱动模型- epoll 的文件描述符集合- epoll 的回调函数3.epoll 的安装与配置- epoll 的编译与安装- epoll 的配置选项- epoll 的错误处理4.使用epoll进行I/O多路复用- 创建epoll 实例- 添加/修改/删除事件- 查询事件- 处理事件5.epoll 的高级特性- epoll 的边缘触发(ET) 与水平触发(LT)- epoll 的批量处理- epoll 的效率与性能6.epoll 在实际项目中的应用- 网络通信应用- 服务器应用- 客户端应用正文:C 语言epoll 详解1.简介C语言epoll是Linux系统下的一种I/O多路复用技术,它允许程序监视多个文件描述符,在某个文件描述符就绪时,就能够进行相应的读写操作。

epoll相比传统的select和poll技术,具有更高的性能和更低的资源消耗。

在Linux系统下,epoll被广泛应用于网络通信、服务器和客户端等场景。

2.epoll 的工作原理epoll 的工作原理主要包括事件驱动模型、文件描述符集合和回调函数。

首先,epoll 会创建一个文件描述符集合,程序可以将需要监视的文件描述符添加到该集合中。

当文件描述符就绪时,epoll 会通过回调函数通知程序进行相应的操作。

这种机制使得程序能够高效地处理I/O 事件,而无需轮询等待。

3.epoll 的安装与配置在编译和安装epoll 时,需要确保相关的库文件和头文件已经正确配置。

此外,epoll 提供了多种配置选项,如设置最大文件描述符数量、超时时间等。

在配置过程中,还需要注意错误处理,以便在出现问题时能够及时发现和处理。

4.使用epoll进行I/O多路复用使用epoll进行I/O多路复用的过程主要包括创建epoll实例、添加/修改/删除事件、查询事件和处理事件。

Linux内核调试机制源代码分析

Linux内核调试机制源代码分析

kimage_entry_t *entry; kimage_entry_t *last_entry; unsigned long destination; unsigned long start; struct page *control_code_page; struct page *swap_page; unsigned long nr_segments; struct kexec_segment segment[KEXEC_SEGMENT_MAX]; /*段数组*/ struct list_head control_pages; struct list_head dest_pages; struct list_head unuseable_pages; /* 分配给崩溃内核的下一个控制页的地址*/ unsigned long control_page; /* 指定特殊处理的标识*/ unsigned int type : 1; #define KEXEC_TYPE_DEFAULT 0 #define KEXEC_TYPE_CRASH 1 unsigned int preserve_context : 1; };
内核 kexec 接口函数说明如下:
extern void machine_kexec(struct kimage *image); /*启动内核映像*/ extern int machine_kexec_prepare(struct kimage *image); /*建立内核映 像所需要的控制页*/ extern void machine_kexec_cleanup(struct kimage *image); extern asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment __user *segments, unsigned long flags); /*装 载内核的系统调用*/ extern int kernel_kexec(void); /*启动内核*/

完成端口详解和EPOLL详解

完成端口详解和EPOLL详解

由图可知,内核开始处理I/O操作到结束的时间段是T2~T3,这个时间 段中用户线程一直处于等待状态,如果这个时间段比较短,则不会有 什么问题,但是如果时间比较长,那么这段时间线程会一直处于挂起 状态,这就会很严重影响效率,所以我们可以考虑在这段时间做些事 情。
• 异步I/O
异步I/O操作则很好的解决了这个问题,它可以使得内核开始处理 I/O操作到结束的这段时间,让用户线程可以去做其他事情,从而提 高了使用效率。
Windows完成端口 Linux Fra bibliotekPOLL 解析
目录
1. Windows完成端口介绍 2. Linux EPOLL介绍
1. Windows完成端口
• 同步I/O与异步I/O 说起完成端口,它的实现机制其实是重叠 I/O实现异步I/O操作,下面就结合同步I/O来 解释下什么是异步I/O。
• 同步I/O 首先我们来看下同步I/O操作,同步I/O操作就是对于同一个I/O对 象句柄在同一时刻只允许一个I/O操作,原理图如下:
• 下面给出两个示例代码,方便大家理解 DWORD nReadByte ; BYTE bBuf[BUF_SIZE] ; OVERLAPPED ov = { 0, 0, 0, 0, NULL } ; // hEvent = NULL ; HANDLE hFile = CreateFile ( ……, FILE_FLAG_OVERLAPPED, …… ) ; ReadFile ( hFile, bBuf, sizeof(bBuf), &nReadByte, &ov ) ; // 由于此时hEvent=NULL,所以同步对象为hFile,下面两句的效果一样 WaitForSingleObject ( hFile, INFINITE ) ; //GetOverlappedResult ( hFile, &ov, &nRead, TRUE ) ; 这段代码在调用ReadFile后会立即返回,但在随后的 WaitForSingleObject或者GetOverlappedResult中阻塞,利用同步对象 hFile进行同步。 这段代码在这里可以实现正常的异步I/O,但存在一个问题,倘若现 在需要对hFile句柄进行多个I/O操作,就会出现问题。

linux poll方法

linux poll方法

linux poll方法Linux poll方法是一种用于在多个文件描述符上进行I/O事件轮询的机制。

它可以有效地管理和监控多个文件描述符,使得我们可以同时处理多个I/O事件而不需要阻塞整个进程。

在本文中,我们将详细介绍poll方法的使用和原理。

一、poll方法介绍poll方法是Linux系统提供的一种I/O多路复用机制,它可以同时监控多个文件描述符上的事件。

与传统的select方法相比,poll 方法具有以下优点:1. 没有文件描述符数量限制:select方法对文件描述符数量有限制,而poll方法可以处理更多的文件描述符。

2. 更高效的事件通知机制:poll方法使用链表来存储文件描述符,当有事件发生时,只需遍历链表即可,而不需要像select方法那样遍历整个文件描述符集。

3. 更灵活的事件类型:poll方法不仅能够监控读、写事件,还可以监控异常事件。

二、poll方法的使用使用poll方法需要以下步骤:1. 创建一个pollfd结构体数组,用于存储文件描述符和事件。

2. 使用poll函数来监视文件描述符上的事件。

3. 根据返回的事件类型,进行相应的处理。

下面是一个简单的示例代码,演示了如何使用poll方法监控多个文件描述符上的读事件:```c#include <stdio.h>#include <unistd.h>#include <sys/poll.h>int main() {struct pollfd fds[2];int timeout = 5000; // 5秒超时// 监控标准输入和标准输出fds[0].fd = STDIN_FILENO;fds[0].events = POLLIN;fds[1].fd = STDOUT_FILENO;fds[1].events = POLLOUT;// 调用poll函数进行事件监控int ret = poll(fds, 2, timeout);if (ret == -1) {perror("poll");return 1;}// 处理返回的事件if (ret > 0) {if (fds[0].revents & POLLIN) {printf("stdin is ready for reading\n");}if (fds[1].revents & POLLOUT) {printf("stdout is ready for writing\n");}} else if (ret == 0) {printf("timeout\n");}return 0;}```三、poll方法的原理poll方法的原理是基于内核的事件驱动机制。

epoll函数

epoll函数

epoll函数epoll函数是Linux操作系统提供的一种高效的IO多路复用机制,能够帮助我们实现高性能的网络编程。

本篇文章将围绕epoll函数展开,分步骤阐述该函数的使用。

一、epoll函数的概述epoll函数用于注册监听多个套接字文件描述符上的事件,并且返回可以进行I/O操作的套接字文件描述符列表。

它是Linux操作系统提供的一种高效的IO多路复用机制。

二、epoll函数的使用步骤以下为epoll函数的使用步骤:1、创建epoll文件描述符当我们创建一个epoll文件描述符时,系统会返回一个int型的文件描述符,该文件描述符用于后续的epoll操作。

int epoll_create(int size);其中,size是epoll的size,即可监听的文件描述符数量。

返回的结果是epoll实例的文件描述符。

2、添加文件描述符到epoll中我们可以通过epoll_ctl函数向指定的epoll中添加/修改/删除对应的文件描述符。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);其中,epfd为epoll实例的文件描述符,op表示操作类型,有以下三种:(1)EPOLL_CTL_ADD:向epoll实例中添加监听的文件描述符;(2)EPOLL_CTL_MOD:修改在epoll实例中已经存在的文件描述符;(3)EPOLL_CTL_DEL:从epoll实例中删除一个监听的文件描述符。

fd表示需要添加/修改/删除的文件描述符,event为epoll_event结构体,用于指定fd上需要监听的事件类型,如:struct epoll_event ev;ev.events = EPOLLIN | EPOLLOUT;ev.data.fd = fd;3、等待epoll事件的发生当我们向epoll示例中添加了文件描述符,并正确地指定了待监视的事件类型,接下来就可以调用epoll_wait函数等待事件的发生了。

[重点]linux源码分析

[重点]linux源码分析

[重点]linux源码分析linux源码分析Linux内核源代码中的C语言代码Linux 内核的主体是以 GNU的 C 语言编写的,GNU为此提供了编译工具gcc。

GNU对 C 语言本身(在 ANSI C 基础上)做了不少扩充,可能是读者尚未见到过的。

另一方面,由于内核代码,往往会用到一些在应用程序设计中不常见的语言成分或编程技巧,也许使读者感到陌生。

本书并非介绍 GNU C语言的专著,也非技术手册,所以不在这里一一列举和详细讨论这些扩充和技巧。

再说,离开具体的情景和上下文,罗列一大堆规则,对于读者恐怕也没有多大帮助。

所以,我们在这里只是对可能会影响读者阅读 Linux 内核源程序,或使读者感到困惑的一些扩充和技巧先作一些简单的介绍。

以后,随着具体的情景和代码的展开,在需要时还会结合实际加以补充。

首先,gcc 从 C++语言中吸收了“inline”和“const”。

其实,GNU 的 C 和C++是合为一体的,gcc既是 C 编译又是 C++编译,所以从 C++中吸收一些东西到 C 中是很自然的。

从功能上说,inline 函数的使用与#define 宏定义相似,但更有相对的独立性,也更安全。

使用 inline函数也有利于程序调试。

如果编译时不加优化,则这些inline 就是普通的、独立的函数,更便于调试。

调试好了以后,再采用优化重新编译一次,这些 inline函数就像宏操作一样融入了引用处的代码中,有利于提高运行效率。

由于 inline 函数的大量使用,相当一部分的代码从.c 文件移入了.h 文件中。

还有,为了支持 64 位的CPU结构(Alpha 就是 64 位的),gcc 增加了一种新的基本数据类型“longlong int”,该类型在内核代码中常常用到。

许多 C 语言都支持一些“属性描述符”(attribute),如“aligned”、“packed”等等;gcc 也支持不少这样的描述符。

这些描述符的使用等于是在 C 语言中增加了一些新的保留字。

linux2.6内核启动分析--李枝果(不看是你的损失^_^)

linux2.6内核启动分析--李枝果(不看是你的损失^_^)

S h e n z h e n F a. lizhiguo0532@ 2010-6-041Linux 2.6lizhiguo0532@ 2010-6-04----------------------------------------------------------------------------------------------------------------------/sz_farsight---------------------------------------------------------------------------------------------------------------------- ^_^SDMakefile uImageMakefile uImage *.o1. arm-linux-gnu-ld arch/arm/kernel/vmlinux.ldsarch/arm/kernel/head.o arch/arm/kernel/init_task.oS h e nz h e n F a r silizhiguo0532@ 2010-6-042 vmlinux.lds2. 3. 4. piggy.gz5.S h e ns i gh t In c . lizhiguo0532@ 2010-6-043piggy.gz piggy.o ld6. arm-linux-gnu-ld arch/arm/boot/compressed/piggy.o27 *(.piggydata) piggydata piggydata Image piggy.gzvmlinux.ldsS h e n zc . lizhiguo0532@ 2010-6-0447.8.uboot arch/arm/boot/compressed/piggy.gz- arch/arm/boot/compressed/piggy.o 0xc0008000 (arch/arm/boot/compressed/vmlinux- arch/arm/boot/zImage) 0x0 0x00000000 0x0 0x30008000 Image vmlinux 0xc0008000S h e n z h e nF a r s i g h t In c . lizhiguo0532@ 2010-6-0450x0 arch/arm/boot/compressed/head.s misc.c 1. uboot thekernelr0—>r8,r1- r7.2. LC00x0 0x300080003. 0x00x30008000 CONFIG_ZBOOT_ROM r2, r3 r5, r6, ip, sp r6 ip got4. clear bss5. cache 4K.align.section ".stack", "w"user_stack: .space 4096S h eh tI nc.lizhiguo0532@ 2010-6-0466.Zreladdr vmlinuxarch/arm/mach-s3c2410/Makefile.bootarch/arm/boot/MakefileS h e nz h e n F a r si gh t I n c .lizhiguo0532@ 2010-6-047 arch/arm/boot/compressed/Makefile ZRELADDR vmlinux ImageuImage load zImage load uImage zImage uboot zImage load entryuImage zImage mkimage uImage -a data load -e entry arch/arm/boot/Makefile0x30008000S h e n z h e n F a r s i g h t In c . lizhiguo0532@ 2010-6-048 r4 Image 0x30008000 r5 zImage r2 zImager4>=r2, r4=0x30800000 Image r2=0x30008000+(zImage+bss size)+stack size 4K + malloc size 64K zImage Image 0x30800000r4+4M<r5, r5=0x30800000 r4=30008000 zImage r4r4+4M>r5, r4=r5=0x30008000 0x30008000@ r0 = malloc end or decompress space,@ r1 = sp end or malloc begin,@ r2 = malloc end ,@ r3 = architecture IDdecompress_kernelmalloc 0x300080007. decompress_kernel in arch/arm/boot/compressed/misc.cS h e nn F a r s i gh t I n c .lizhiguo0532@ 2010-6-049Gunzip() lib/inflate.c gunzip 8. 128add r0, r0, #127bic r0, r0, #127 @ align the kernel length9 head.S 0x30008000R1 128 r2 reloc_start r3 reloc_end head.Scache_clean_flush cache cache reloc_startzImage gdb9. reloc_startS h e n z h enF a r s i g h t I n c . lizhiguo0532@ 2010-6-0410* r0 = decompressed kernel length * r1-r3 = unused* r4 = kernel execution address* r5 = decompressed kernel start* r6 = processor ID* r7 = architecture ID* r8-r14 = unused0x30008000 cache r0 r1 pc 0x30008000 /node/3VMLINUX arch/arm/kernel/head.S init/Main.c 0x0 0xC0008000Mmu I Cache D Cache r0=0 r1=architecture ID arch/arm/kernel/vmlinux.lds stext1. SVC FIR IRQ2. __lookup_processor_type cp15 cpuid .init proc_info_list cpu3. __lookup_machine_type uboot machinearchitecture number .init machine number machine_descS h e n z h n F a r si g h t I n c .lizhiguo0532@ 2010-6-0411 ……………………arch-arm-kernel-head.Sarch-arm-kernel-head/node/4start_kernel in init/Main.c1. printk(linux_banner)2. a. setup_processor()proc_info_list list cpu_name cpuname idproc_arch system_utsname= list->arch_name armv4telf_platform= list->elf_name v4 elf_hwcap = list->elf_hwcap;/* 1|2|4 */ cpu_proc_init()Cpu-single.h#define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init)#define __cpu_fn(name,x) __catify_fn(name,x)#define __catify_fn(name,x) name##xCPU_NAME = cpu_arm920cpu_proc_init(); cpu_arm920_proc_init()proc_arm920.S b. mdesc = setup_machine(machine_arch_type).init machine_desclist list-namec. machine_name = mdesc->name machine_named. tags = phys_to_virt(mdesc->boot_params)uboot 0x300001000xc0000100e.if (tags->hdr.tag == ATAG_CORE) {if (meminfo.nr_banks != 0) /* meminfo defined in setup.c */squash_mem_tags(tags);parse_tags(tags);}static struct meminfo meminfo __initdata = { 0, };in steup.cparse_tags(tags) in steup.cS h e n z h e n F a r s i g h t In clizhiguo0532@ 2010-6-0412Steup_arch()- parse_tags()- parse_tag(), all function in steup.c __tagtable_begin, __tagtable_end arch/arm/kernel/vmlinux.ldsparse_tag()parseIgnoring unrecognised tag 0x%08x\n ubootf. struct mm_struct init_mm = INIT_MM(init_mm);init_mm.start_code = (unsigned long) &_text;init_mm.end_code = (unsigned long) &_etext;init_mm.end_data = (unsigned long) &_edata;init_mm.brk = (unsigned long) &_end;_text, _etext, _edata, _end arch/arm/kernel/vmlinux.ldsg. parse_cmdline(cmdline_p, from) uboot commond_linefrom command_linecommand_linestart_kernerl mem initrdstart_kernel()->parse_option() mem initrdcommand_line *cmdline_pstart_kernelmem initrdh. paging_init(&meminfo, mdesc);/**/ in arch/arm/mm/init.cmemtable_init(mi)/bbstcon,board,Embedded,reid,1165977462.html0xffff0000mdesc->map_io() smdk2410arch/arm/mach-s3c2410/mach-smdk2410.c Linux , smdk2410_map_io() 1 iotable_init(s3c_iodesc, GPIO,IRQ,MEMCTRL,UARTS h e nz h e n F a r s i gh t In c . lizhiguo0532@ 2010-6-0413 2 (cpu->map_io)(mach_desc, size) LCD, map.h S3C2410_ADDR(x) ((void __iomem *)0xF0000000 + (x)) IO 0xF0000000 1M 1. GPIO IRQ UART MEMCRTL WATCHDOG USB 2. kmalloc 0x30008000 phys_to_virt virt_to_ phys 3. mmu TTB 0x30004000 16K mmu arch/arm/kernel/head.S 4M mmu sector Uarth.request_standard_resources(&meminfo, mdesc) memory kernel_text kernel_data video_ram new new resource NULLi. cpu_init() in arch/arm/kernel/setup.ccpu cpu id cache IRQ ABT UND stack 12 svci. __mach_desc_SMDK2410_typeinit_arch_irq init_machine system_timer3. sched_init()init_idle (current, smp_processor_id()) idle4. preempt_disable()5. (zone) build_all_zonelists()6. printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line); uboot command_line setup_arch7. parse_early_param()S h e n z h e n F a r s i g h t In c . lizhiguo0532@ 2010-6-0414 __setup setup_arch &command_line command_linesaved_command_line8. parse_args("Booting kernel", command_line, __start___param,__stop___param - __start___param,&unknown_bootoption);parse_early_param(); setup paramcommand_line setup_arch__start___param param System.map__stop___param - __start___paramunknown_bootoption paramparse_one()parse_one() param __setupLinux bootargs9. sort_main_extable()__start___ex_table __stop___ex_table *(__ex_table) struct exception_table_entry insn10. setup_arch- paging_init- memtable_initinit_maps, alloc_bootmem_low_pages ARM 0xFFFF0000 0xFFFF0000trap_init .Lcvectors 0xffff0000 __stubs_start __stubs_end 0xffff0200 0xffff0500 0xffff0000 cache DOMAIN_USER DOMAIN_MANAGER DOMAIN_CLIENT11.rcu_init() cpu struct rcu_dataper_cpu_rcu_data per_cpu_rcu_bh_data.12.init_IRQstruct irqdesc irq_desc[NR_IRQS], irq_desc[n] bad_irq_desc pendS h e nz h e n F a r s i gh t I n c . lizhiguo0532@ 2010-6-0415 init_arch_irq setup_arch smdk2410_init_irq in mach-smdk2410.cs3c24xx_init_irq do_level_IRQ do_edge_IRQ __do_irquart ADC13.pidhash_init()pid_hash hash pidhash_shift pidhash_shift min 12 hash hash pid_hash[n](n=1~3), hash hash struct hlist_head first NULL14.init_timers()struct tvec_t_base_s per_cpu_tvec_bases, per_cpu_tvec_bases lock15.softirq_initS h e n z h e n F a r s i gh t I n c .lizhiguo0532@ 2010-6-041616.time_init() timersetup_archtime_init if s3c2410_timer_init timer417.console_initprintk log_bufa. tty_register_ldisc TTYtty ttyttytty ttyS h e n z h e n F ar s i g h t I n c . lizhiguo0532@ 2010-6-0417 ppp tty tty b. s3c24xx_serial_initconsole /*vmlinux.lds.S__con_initcall_start = .;*(.con_initcall.init)__con_initcall_end = .;con_initcall.initfn .con_initcall.init :#define console_initcall(fn) \static initcall_t __initcall_##fn \__attribute_used____attribute__((__section__(".con_initcall.init")))=fn*///:console_initcall(s3c24xx_serial_initconsole);//:start_kernel->console_init->s3c24xx_serial_initconsolecall = __con_initcall_start; /* console_initcall */while (call < __con_initcall_end) {(*call)();call++;}18.profile_init()/* *///profile// bootargs profile/*profile menuconfig profiling support1. profileprofile profile=1 profile=schedule 12. /proc/profile readprofilereadprofile -m /proc/kallsyms | sort -nr > ~/cur_profile.log,readprofile -r -m /proc/kallsyms |sort -nr,readprofile -r && sleep 1 && readprofile -m /proc/kallsymsS h e n z h e n F a r s i g h t In c . lizhiguo0532@ 2010-6-0418|sort -nr >~/cur_profile.log 3. /proc/profile profile profile=?profile=schedule ? schedule schedule*/19.local_irq_enable()IRQ20.mem_init()alloc_bootmem(),alloc_bootmem_low(),alloc_bootmem_pages()21.kmem_cache_init()slab22. numa_policy_init();if (late_time_init)late_time_init();calibrate_delay();// BogMIPS23. pidmap_init();pgtable_cache_init();prio_tree_init();/*index_bits_to_maxindex[BITS_PER_LONG]index_bits_to_maxindex[n] -1index_bits_to_maxindex[BITS_PER_LONG-1] ~0UL*/24 anon_vma_init();/*kmem_cache_creat() struct anon_vmakmem_cache_t anon_vma ,void anon_vma_ctor NULLkmem_cache_t anon_vma_chachepS h e n z h e n F a r s i g h tlizhiguo0532@ 2010-6-0419 */ 25. fork_init(num_physpages);/* */ 26. proc_caches_init();buffer_init();/*kmem_cache_create("buffer_head",sizeof(struct buffer_head), 0,SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_buffer_head, NULL) struct buffer_head kmem_cache_t */27. security_init();/* */28. vfs_caches_init(num_physpages);radix_tree_init();signals_init();kmem_cache_create("sigqueue",sizeof(struct sigqueue),__alignof__(struct sigqueue),SLAB_PANIC, NULL, NULL) struct sigqueue kmem_cache_t sigqueue cache line kmem_cache_t sihqueue_cachep.29. page_writeback_init()buffer_pages.30. proc_root_init();/* proc CONFIG_PROC_FS */31. check_bugs();/* arm */32 rest_init()initlinux :0 rest_init()a. in arch/arm/kernel/process.cinitb. schedule() idle schedulec. cpu_idle()0S h e n z h e n F a r s i g h t In c . lizhiguo0532@ 2010-6-0420 init in main.c a. lock_kernel() lock b. smpc. populate_rootfs() initcallsd. do_basic_setup()#define module_init(x) __initcall(x);#define __initcall(fn) device_initcall(fn)#define core_initcall(fn) __define_initcall("1",fn)#define postcore_initcall(fn) __define_initcall("2",fn) #define arch_initcall(fn) __define_initcall("3",fn) #define subsys_initcall(fn) __define_initcall("4",fn) #define fs_initcall(fn) __define_initcall("5",fn) #define device_initcall(fn) __define_initcall("6",fn) #define late_initcall(fn) __define_initcall("7",fn)#define __define_initcall(level,fn) \static initcall_t __initcall_##fn __attribute_used__ \__attribute__((__section__(".initcall" level ".init"))) = fn include/linux/init.harch_initcall initcall module_init init 1 do_basic_setup do_initcalls()S h e n z h e n F a r s i gh t I n c . lizhiguo0532@ 2010-6-0421 Start_kernel * -- rest_init()* -- kernel_thread()* init 1 -- Init* -- populate_rootfs() -- do_basic_setup()* initcall modlue_init -- init_workqueues() -- usermodehelper_init() khelper-- driver_init()-- sysctl_init()-- sock_init() socket-- do_initcalls()*-- (*call)()* initcall-- prepare_namespace()-- name_to_dev_t()root bootargs root=/dev/** root=31:03 /dev/mtdblock3 root /dev/ 31-- mount_root();/* */-- free_initmem() init:Freeing init memory: 116K-- sys_open() and sys_dup(0) 0 1 2-- run_init_process(execute_command) init=/initrd command_line-- cpu_idle() 0init 1 …… run_init_process("/sbin/init");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");……S h n n F a r s i g h t In c . lizhiguo0532@ 2010-6-0422 ARM Linux -- -PXA255--- Linux bootargs/u3/99423/article.html/bbstcon,board,Embedded,reid,1165977462.html/node/4。

什么是epoll

什么是epoll

什么是epollepoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll。

当然,这不是2.6内核才有的,它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44),它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。

epoll的相关系统调用epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用。

1. int epoll_create(int size);创建一个epoll的句柄。

自从linux2.6.8之后,size参数是被忽略的。

需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux 下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll 后,必须调用close()关闭,否则可能导致fd被耗尽。

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数,它不同于select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

第一个参数是epoll_create()的返回值。

第二个参数表示动作,用三个宏来表示:EPOLL_CTL_ADD:注册新的fd到epfd中;EPOLL_CTL_MOD:修改已经注册的fd的监听事件;EPOLL_CTL_DEL:从epfd中删除一个fd;第三个参数是需要监听的fd。

第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:[cpp]view plaincopyprint?1.//保存触发事件的某个文件描述符相关的数据(与具体使用方式有关)2.3.typedef union epoll_data {4.void *ptr;5. int fd;6. __uint32_t u32;7. __uint64_t u64;8.} epoll_data_t;9.//感兴趣的事件和被触发的事件10.struct epoll_event {11. __uint32_t events; /* Epoll events */12. epoll_data_t data; /* User data variable */13.};events可以是以下几个宏的集合:EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);EPOLLOUT:表示对应的文件描述符可以写;EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);EPOLLERR:表示对应的文件描述符发生错误;EPOLLHUP:表示对应的文件描述符被挂断;EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

linux2.6.9 epoll系统调用源码分析一、相关的数据结构1、struct eventpollstruct eventpoll {/* Protect the this structure access *//*读写锁*/rwlock_t lock;/** This semaphore is used to ensure that files are not removed* while epoll is using them. This is read-held during the event* collection loop and it is write-held during the file cleanup* path, the epoll file exit code and the ctl operations.*//*读写信号量*/struct rw_semaphore sem;/* Wait queue used by sys_epoll_wait() */wait_queue_head_t wq;/* Wait queue used by file->poll() */wait_queue_head_t poll_wait;/* List of ready file descriptors *//*已完成的操作时间队列*/struct list_head rdllist;/* RB-Tree root used to store monitored fd structs *//*红黑树的跟,保存epoll监视的文件描述符*/struct rb_root rbr;};该结构体用来保存与epoll节点关联的多个文件描述符,保存的方式是使用红黑树实现的hash表。

2、struct ep_pqueue/* Wrapper struct used by poll queueing */struct ep_pqueue {poll_table pt;struct epitem *epi;};这个结构体类似于select/poll中的struct poll_wqueues。

由于epoll需要在内核态保存大量信息,所以光光一个回调函数指针已经不能满足要求,所以在这里引入了一个新的结构体struct epitem。

3、struct epoll_eventstruct epoll_event {__u32events;__u64data;} EPOLL_PACKED;4、struct epitem/** Each file descriptor added to the eventpoll interface will* have an entry of this type linked to the hash.*/struct epitem {/* RB-Tree node used to link this structure to the eventpoll rb-tree *//*红黑树节点,将本节点挂载到eventpoll 所对应的红黑树*/ struct rb_node rbn;/* List header used to link this structure to the eventpoll ready list *//*双向链表,用来将该节点链接到已完成队列上*/struct list_head rdllink;/* The file descriptor information this item refers to *//*这个结构体对应被监听的文件描叙符信息*/struct epoll_filefd ffd;/* Number of active wait queue attached to poll operations *//*poll操作中事件的个数*/int nwait;/* List containing poll wait queues *//*双向链表,保存着被监视文件的等待队列,功能*//*类似于select/poll中的poll_table*/struct list_head pwqlist;/* The "container" of this item *//*指向eventpoll,多个epitem对应一个eventpoll*/struct eventpoll *ep;/* The structure that describe the interested events and the source fd *//*记录发生的时间和对应fd*/struct epoll_event event;/** Used to keep track of the usage count of the structure. This avoids* that the structure will desappear from underneath our processing.*//*引用计数*/atomic_t usecnt;/* List header used to link this item to the "struct file" items list *//*双向链表,用来链接被监视的文件描述符对应的struct file。

因为file 里有f_ep_link,用来保存所有监视这个文件的epoll节点*/struct list_head fllink;/* List header used to link the item to the transfer list *//*双向链表,用来保存传输队列*/struct list_head txlink;/** This is used during the collection/transfer of events to userspace* to pin items empty events set.*//*文件描述符的状态,在收集和传输时用来锁住空的事件集合*/unsigned int revents;};5、eppoll_entry/* Wait structure used by the poll hooks */struct eppoll_entry {/* List header used to link this structure to the "struct epitem" */struct list_head llink;/* The "base" pointer is set to the container "struct epitem" */void *base;/** Wait queue item that will be linked to the target file wait* queue head.*/wait_queue_t wait;/* The wait queue head that linked the "wait" wait queue item */wait_queue_head_t *whead;};6、epoll_filefdstruct epoll_filefd {struct file *file;int fd;};二、源码分析1、eventpoll_init函数源码static int__init eventpoll_init(void){int error;init_MUTEX(&epsem);/* Initialize the structure used to perform safe poll wait head wake ups */ep_poll_safewake_init(&psw);/* Allocates slab cache used to allocate "struct epitem" items */epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem),0, SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|SLAB_PANIC,NULL, NULL);/* Allocates slab cache used to allocate "struct eppoll_entry" */pwq_cache = kmem_cache_create("eventpoll_pwq",sizeof(struct eppoll_entry), 0,EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL);/** Register the virtual file system that will be the source of inodes* for the eventpoll files*//*注册了一个新的文件系统,叫"eventpollfs"(在eventpoll_fs_type结构里),然后挂载此文件系统*/error = register_filesystem(&eventpoll_fs_type);if (error)goto epanic;/* Mount the above commented virtual file system */eventpoll_mnt = kern_mount(&eventpoll_fs_type);error = PTR_ERR(eventpoll_mnt);if (IS_ERR(eventpoll_mnt))goto epanic;DNPRINTK(3, (KERN_INFO"[%p] eventpoll: successfully initialized.\n",current));return 0;epanic:panic("eventpoll_init() failed\n");}epoll是个module,所以先看看module的入口eventpoll_init。

这个module在初始化时注册了一个新的文件系统,叫"eventpollfs"(在eventpoll_fs_type结构里),然后挂载此文件系统。

相关文档
最新文档