一,poll
允许进程决定是否可以对一个或者多个打开的文件做非阻塞的读取或者写入(但是请注意select自身会阻塞进程知道某个描述符满足条件或者超时),常常用于那些要使用多个输入或者输出流而又不会阻塞于其中任何一个流的应用程序中,比如telnet程序,需要2个输出,2个输入流而又不希望阻塞。
unsigned int (*poll)(struct file *filp,poll_table *wait);//把当前的文件指针挂到设备内部定义的等待 队列中。这里的参数table可以不考虑,是在select函数实现过程中的一个内部变量
该驱动方法一般分为两步:
1) 在一个或者多个可指示poll状态变化的等待队列上调用poll_wait.如果当时没有文件描述符可来执行I/O,则内核将使进程在传递到该系统调用的所有文件描述符对应的等待队列上等待。
void poll_wait(struct file *,wait_queue_head_t *,poll_table *);
2) 返回一个用来描述操作是否可以立即无阻塞执行的位掩码.
可读取返回POLLIN | POLLRDNORM;
可写入返回POLLOUT | POLLWRNORM;
使用非阻塞和阻塞操作的组合以及select方法可以有效地查询设备,但是对于某些情况却不是很适用,此时我们需要使用异步通知的方法。
二,select //经常用于socket编程
原型:int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
1)struct fd_set:可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。
fd_set集合可以通过一些宏由人为来操作,比如
FD_ZERO(fd_set *);//清空集合
FD_SET(int ,fd_set*);//将一个给定的文件描述符加入集合之中
FD_CLR(int,fd_set*);//将一个给定的文件描述符从集合中删除
FD_ISSET(int ,fd_set* );//检查集合中指定的文件描述符是否可以读写
2)struct timeval:是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是微妙数。
具体解释select的参数:
1>int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错
2>fd_set *readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
3>fd_set *writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
4>fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。
5>struct timeval *timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
返回值:
负值:select错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件
在有了select后可以写出像样的网络程序来!举个简单的例子,就是从网络上接受数据写入一个文件中。
例子:
select()函数与Linux驱动程序的关系
当用户调用select系统调用时,select系统调用会先调用poll_initwait(&table);,然后调用驱动程序中 struct file_operations下的fop->poll函数,在这个函数里应该调用poll_wait(),将current加到某个等待队列(这里调用poll_wait()),并检查是否有效,如果无效就调用schedule_timeout();去睡眠。事件发生后,schedule_timeout()回来,,调用fop->poll();,检查到可以运行,就调用poll_freewait(&table);从而完成select系统调用。重要的是fop->poll()里面要检查是否就绪,如果是,要返回相应标志。
三,epoll
epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
epoll的接口非常简单,一共就三个函数:
1) int epoll_create(int size);
创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好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()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。
epfd: 是epoll_create()的返回值
op:表示动作,用三个宏来表示:
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
fd:是需要监听的fd
event:告诉内核需要监听什么事,struct epoll_event结构如下:
events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
3) int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。
分享到:
相关推荐
本节我们将深入探讨Linux设备驱动中的一个关键话题:高级字符驱动程序操作,特别是设备文件的访问控制。这在编写高效、安全的设备驱动时至关重要。 1. **字符设备文件**: 在Linux中,设备被抽象为文件,分为字符...
Linux驱动程序是操作系统与硬件设备之间的重要桥梁,它使得Linux系统能够识别并有效利用硬件资源。这份"Linux驱动基础代码笔记ppt"包含了达内培训的精华内容,旨在帮助初学者理解Linux驱动的基本概念、开发流程以及...
- **用途**:此函数用于支持`poll`、`epoll`和`select`系统调用,检查是否有数据可读或可写。 - **参数**:指向`struct file`的指针和指向`struct poll_table_struct`的指针。 - **返回值**:位掩码表示哪些操作是非...
- **多路复用**:使用`select`、`poll`或`epoll`等函数监控多个文件描述符的状态变化。 - **信号驱动IO**:通过信号通知来告知应用程序数据是否可用。 - **异步IO**:应用程序可以在数据实际传输时执行其他任务,...
在嵌入式Linux系统中,驱动程序是连接硬件与操作系统之间的桥梁,负责管理和控制硬件设备。"国嵌嵌入式Linux驱动进阶班实验2.1-2.2"是一系列针对驱动开发深入学习的实践课程,旨在帮助学员提升驱动程序设计与调试的...
- 多路复用技术:掌握select、poll、epoll等多路复用技术的应用。 #### 三、ARM程序设计与系统移植 **3.1 ARM处理器概述** - 处理器类型:了解ARM处理器的不同系列及其特点。 - 工作模式:掌握ARM处理器的工作模式...
Linux支持多种I/O模型,包括阻塞I/O、非阻塞I/O、异步I/O和复用I/O(如select、poll、epoll)。这些模型各有优缺点,开发者根据应用需求选择合适的模型进行编程。例如,阻塞I/O适合对响应时间不敏感的应用,而异步I...
在IT行业中,Linux操作系统因其开源、稳定和高效的特点,常被用于开发高性能的服务端应用。在本项目中,"linux写的基于epoll技术的socket tcp服务器,数据库采用mysql.zip",开发者利用了Linux的epoll机制来实现了一...
- 多路复用:select、poll、epoll机制。 - 客户端-服务器模型的应用。 8. **实时性与嵌入式性能优化**: - 实时操作系统(RTOS)概念,软实时和硬实时的区别。 - 性能分析工具,如gprof、strace等。 - 代码...
6. **多路复用技术**:如上所述,非阻塞I/O通常配合select、poll或epoll等机制,监控多个文件描述符的状态,一旦有数据准备就绪,就可以立即处理,提高效率。 7. **DMA(直接内存访问)**:对于大流量的数据传输,...
《嵌入式Linux应用程序开发标准教程》第二版全面涵盖了嵌入式系统开发的关键技术,包括操作系统内核、编程语言、开发环境以及特定领域的应用。以下将根据提供的文件名称,解析出其中涉及的主要知识点: 1. **Linux...
- select/poll/epoll:这些机制允许一个进程监控多个文件描述符,等待任意一个描述符就绪时再进行操作,提高了并发处理能力。 8. **异步I/O模型(AIO)** - AIO模型在数据准备好后通知应用程序,使得程序可以在...
6. **网络编程**:介绍套接字API,包括TCP/IP协议栈、服务器与客户端编程、异步I/O、多路复用技术如select、poll和epoll。 7. **内存管理**:讨论动态内存分配与释放(malloc、calloc、realloc、free)、内存映射...
本章“第6章、文件IO编程”深入探讨了这一关键主题,旨在帮助嵌入式Linux应用程序开发人员理解和掌握高效、安全的文件操作技巧。以下是关于Linux文件I/O编程的详细讲解。 一、文件系统基础 在Linux中,一切皆为文件...
相比于传统的select和poll,epoll提供了更优秀的性能和扩展性,特别是在大量文件描述符的情况下。 在这个项目中,`timer_queue.py`很可能是实现了定时器队列的主逻辑。这个队列可能包含了一些定时任务,每个任务都...
在Linux系统中,字符设备(Character Device)是操作系统提供的一种基本I/O接口,它允许用户空间的程序直接与硬件交互,比如键盘、鼠标、串口等。本项目"chardev-1.2.rar"是一个简单的字符设备驱动示例,配合聊天...
此外,还有`select()`, `poll()`, `epoll`等多路复用I/O机制,用于高效处理大量并发连接。 6. **设备驱动**:Linux内核的驱动模型允许开发者编写代码来控制硬件设备。2.6.2.26内核的驱动框架包括字符设备驱动、块...
- 异步I/O和信号驱动I/O:了解select、poll和epoll等机制,以处理并发I/O事件。 5. **系统调用与API** - 系统调用:Linux系统调用是程序与内核交互的方式,如open、close、read、write等。 - Glibc库:GNU C ...