UNIX环境高级编程——I/O多路转接(select、pselect和poll)
I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回。在返回时,它告诉进程哪些描述符已准备好可以进行I/O。
poll、pselect和select这三个函数使我们能够执行I/O多路转接。
一、select函数
在所有依从POSIX的平台上,select函数使我们可以执行I/O多路转接。传向select的参数告诉内核:
- 我们所关心的描述符。
- 对于每个描述符我们所关心的状态。(是否读一个给定的描述符?是否想写一个给定的描述符?是否关心一个描述符异常状态?)
- 愿意等待多长时间(可以永远等待,等待一个固定量时间或完全不等待)。
从select返回时,内核告诉我们:
- 已准备好的描述符的数量。
- 对于读、写或异常这三个状态中的每一个,哪些描述符已准备好。
#include <sys/select.h>
int select(int maxfdp1,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *tvptr);//返回值:准备就绪的描述符数,若超时则返回0,若出错则返回-1
先说明最后一个参数,它指定愿意等待的时间:
struct timeval{
long tv_sec; //seconds
long tv_usec;//and microseconds
}
有三种情况:
- tvptr == NULL
永远等待。如果捕捉到一个信号则中断此无限期等待。当所指定的描述符中的一个已准备好或捕捉到一个信号则返回。如果捕捉到一个信号,则select返回-1,errno设置为EINTR
- tvptr->tv_sec == 0 && tvptr->tv_usec == 0
完全不等待。测试所有指定的描述符并立即返回。
- tvptr->tv_sec != 0 || tvptr->tv_usec != 0
等待指定的秒数和微妙数。当指定的描述符之一已准备好或当指定的时间值已经超过时立即返回。如果在超时时还没有一个描述符准备好,则返回值是0.与第一种情况一样,这种等待可被捕捉到的信号中断。
#include <sys/select.>
int FD_ISSET(int fd,fd_set *fdset);//返回值:若fd在描述符集中则返回非0值,否则返回0
void FD_CLR(int fd,fd_set *fdset);
void FD_SET(int fd,fd_set *fdset);
void FD_ZERO(fd_set *fdset);
- 调用FD_ZERO将一个指定的fd_set变量的所有位设置为0.
- 调用FD_SET设置一个fd_set变量的指定位。
- 调用FD_CLR则将一指定位清除。
- 调用FD_ISSET测试一指定位是否设置。
select的中间三个参数(指向描述符集的指针)中的任意一个或全部都可以是空指针,这表示对相应状态并不关心。如果所有三个指针都是空指针,则select提供了较sleep更精确的计时器。
select的第一个参数maxfdp1的意思是“最大描述符加1”。在三个描述符集中找出最大描述符值,然后加1,这就是第一个参数。也可以将第一个参数设置为FD_SETSIZE,这是<sys/select.h>中的一个常量,它说明了最大的描述符(经常是1024)。如果将第一个参数设置为我们关注的最大描述符编号值加1,内核就只需在此范围内寻找打开的位,而不必在三个描述符集中的数百位内搜索。
fd_set readset,writeset;
FD_SERO(&readset);
FD_ZERO(&writeset);
FD_SET(0,&readset);
FD_SET(3,&readset);
FD_SET(1,&writeset);
FD_SET(2,&writeset);
select(4,readset,&writeset,NULL,NULL);
- 返回-1表示出错。出错是有可能的,例如在所指定的描述符都没有准备好时捕捉到一个信号。在此种情况下,将不修改其中任何描述符集。(即原先描述符值1的还是保持1,不变)
- 返回0表示没有描述符准备好。若指定的描述符都没有准备好,而且指定的时间已经超时,则发生这种情况。此时,所有描述符集皆被清0。
- 正返回值表示已经准备好的描述符数,该值是三个描述符集中已经准备好的描述符数之和,所以如果同一描述符已准备好读和写,那么在返回值中将计2。在这种情况下,三个描述符集中仍旧打开的位对应于已准备好的描述符,其他没有准备好的清0。
#include <sys/select.h>
int pselect(int maxfdp1,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const struct timespec *tsptr,const sigset_t *sigmask);//返回值:准备就绪的描述符数,若超时则返回0,若出错则返回-1
除以下几点,pselect与select相同:
- select的超时值用timeval结构指定,但pselect使用timespec,timespec结构以秒和纳秒表示超时值,而非秒和微妙。如果平台支持这样精细的粒度,那么timespec就提供了更精准的超时时间。
- 对于pselect可使用一可选择的信号屏蔽字。若sigmask为空,那么在与信号有关的方面,pselect的运行状况和select相同。否则,sigmask指向一信号屏蔽字,在调用pselect时,以原子操作的方式安装该信号屏蔽字。在返回时恢复以前的信号屏蔽字。
#include <poll.h>
int poll(struct pollfd fdarray[],nfds_t nfds,int timeout);
与select不同,poll不是为每个状态(可读性、可写性和异常状态)构造一个描述符集,而是构造一个pollfd结构数组,每个数组元素指定一个描述符编号以及对其关心的状态。
struct pollfd{
int fd; //file descriptor to check,or < 0 ignore
short events; //events of interest on fd
short revents; //events that occurred on fd
}
fdarray数组中的元素数由nfds说明。
应将每个数组元素的events成员设置为下图。通过这些值告诉内核我们对该描述符关心的是什么。返回时,内核设置revents成员,以说明对于该描述符已经发生了什么事件。(注意:poll没有更改events成员,这与select不同,select修改其参数以指示哪一个描述符已准备好了)
poll的最后一个参数说明我们愿意等待时间。有三种不同的情形:
- timeout == -1 永远等待。当所指定的描述符中的一个已准备好,或捕捉到一个信号时则返回。如果捕捉到一个信号,则poll返回-1,errno设置为EINTR。
- timeout == 0 不等待。
- timeout > 0 等待timeout毫秒。当指定的描述符之一已准备好,或指定的时间值已超过时立即返回。如果已超时,但是还没有一个描述符准备好,则返回值是0。
UNIX环境高级编程——I/O多路转接(select、pselect和poll)的更多相关文章
- (十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- 《UNIX环境高级编程(第3版)》
<UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...
- (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- multiple definition of `err_sys' 《UNIX环境高级编程》
本文地址:http://www.cnblogs.com/yhLinux/p/4079930.html 问题描述: [点击此处直接看解决方案] 在练习<UNIX环境高级编程>APUE程序清单 ...
- unix环境高级编程基础知识之第二篇(3)
看了unix环境高级编程第三章,把代码也都自己敲了一遍,另主要讲解了一些IO函数,read/write/fseek/fcntl:这里主要是c函数,比较容易,看多了就熟悉了.对fcntl函数讲解比较到位 ...
- (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
随机推荐
- Just for mysql
mysql的下载与安装 由于学校开设了数据库专业,并且最近准备在做一个web端的设计,虽然本人是负责前端(当然,前端技术也很LOW),但因种种原因,准备开始学习数据库相关的知识,以mysql为例. 昨 ...
- 利用css3+js实现简单带立体过渡效果的图片切换(chrome浏览器)
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
- Spring使用webjar
注意事项 这玩意很简单,但是我们第一次搞就是搞不成功,为什么呢?因为我们都用的是idea或者eclipse编译.webjar只能在maven上才能打包,所以在使用时,记得maven-clean和mav ...
- 微信小程序开发 导入文件说没找到.json的问题
这个真的坑爹 网上的答案也没几个靠谱 说白了就是找个空文件直接创建 然后复制粘贴 反应了这玩意ide不成熟 进去之后直接创了个quick start的源码 也就是我们看的这个网页建议我们下载的源码 老 ...
- Jvm原理剖析与调优之内存结构
一些不得不说的概念 JVM JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机包括一套字节码指令集.一组寄存器.一个栈.一个 ...
- Java线程池使用和常用参数
多线程问题: 1.java中为什么要使用多线程使用多线程,可以把一些大任务分解成多个小任务来执行,多个小任务之间互不影像,同时进行,这样,充分利用了cpu资源. 2.java中简单的实现多线程的方式 ...
- Linux文件管理笔记
1)Linux识别磁盘:Linux通过不同的设备节点区分各个分区,节点名字的由磁盘名加分区号组成.例如,驱动器/dev/hba上的第一个分区叫做/dev/hba1,驱动器/dev/sdc上的第七个分区 ...
- vue+node.js+webpack开发微信公众号功能填坑——v -for循环
页面整体框架实现,实现小功能,循环出数据,整体代码是上一篇 vue+node.js+webpack开发微信公众号功能填坑--组件按需引入 修改部门代码 app.vue <yd-flexbox&g ...
- jQuery CSS 类
通过 jQuery,可以很容易地对 CSS 元素进行操作. jQuery 操作 CSS jQuery 拥有若干进行 CSS 操作的方法.我们将学习下面这些: addClass() - 向被选元素添加一 ...
- Android仅2步实现 滚粗 汉堡导航栏效果~ 全新底部导航交互(滑动隐藏)
本文同步自wing的地方酒馆 布吉岛大家有木有看这一篇文章,再见,汉堡菜单,我们有了新的 Android 交互设计方案 本库下载地址:https://github.com/githubwing/Bye ...