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 环境高级编 ...
随机推荐
- setTimeout、setInterval被遗忘的第三个参数
一.最近在看promise,惊奇的发现:原来 setTimeout不只有两个参数,我还能说什么呢?赶紧探探究竟. function multiply(input) { return new Promi ...
- Docker 第一篇 认识Docker 的作用好处
Docker 第一篇 认识Docker 的作用好处 (1)什么是Docker (2)Docker 优势劣势 Docker是去年开始关注并学习的,因为项目用到了AspnetCore 了解了之后总感觉会用 ...
- 无忧代理免费ip爬取(端口js加密)
起因 为了训练爬虫技能(其实主要还是js技能-),翻了可能有反爬的网站挨个摧残,现在轮到这个网站了:http://www.data5u.com/free/index.shtml 解密过程 打开网站,在 ...
- 聊聊jstack的工作原理
实现一个jstack 在聊Jstack得工作原理前呢,不如让我们先写一个简单的jstack玩玩.不用怕,很简单的,就几行代码的事,看: public class MyJstack { public s ...
- Android源码解析——AsyncTask
简介 AsyncTask 在Android API 3引入,是为了使UI线程能被正确和容易地使用.它允许你在后台进行一些操作,并且把结果带到UI线程中,而不用自己去操纵Thread或Handler.它 ...
- Android studio 中引用jar的其实是Maven?(一)
由于Studio比eclipse多了一步对工程构建的步骤,即为build.gradle这个文件运行,因此其引入第三方开发jar包与lib工程对比Eclipse已完成不同,引入第三方jar与lib工程显 ...
- Java web文件上传下载
[版权申明:本文系作者原创,转载请注明出处] 文章出处:http://blog.csdn.net/sdksdk0/article/details/52048666 作者:朱培 ID:sdksdk0 邮 ...
- MacOS和iOS开发中异步调用与多线程的区别
很多童鞋可能对Apple开发中的异步调用和多线程的区别不是太清楚,这里本猫将用一些简单的示例来展示一下它们到底直观上有神马不同. 首先异步调用可以在同一个线程中,也可以在多个不同的线程中.每个线程都有 ...
- Xcode Organizational Identifiers
操作系统(不管是iOS或是OS X)使用bundle标识去唯一标识你的应用.Bundle标识由一个组织id和你App的名字组成. 一般的,组织id是你域名的反转.如果你的域名是example.com那 ...
- 大数据基础知识问答----hadoop篇
handoop相关知识点 1.Hadoop是什么? Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速 ...