多路IO复用 select 和 poll 函数简介
来源:互联网 发布:重庆行知小小学校招聘 编辑:程序博客网 时间:2024/05/21 02:35
1、多路IO复用的概念
这里有一篇通俗易懂的文件介绍了多路IO的概念http://www.linuxidc.com/Linux/2013-03/80704.htm。当我们需要操作多个文件时,比如我们需要读多个套接字里面的内容,但我们并不知道什么时候套接字里会有数据,如果一直在某一个套接字上阻塞,这时候就不能处理其他套接字,这样会使实时性大打折扣。但是我们就想了,为什么不用非阻塞的方式,使用轮询的方式?轮询的方式确实可以实现,但效率低下,因为我们在需要不停的去“查看”里面有没有数据,即使里面什么也没有。于是我们就想有没有一种方法,在套接字里面有数据时就通知我们,让我们及时去处理,而没有数据时,我们可以不用去理,转而处理其他的事件,这就是多路IO由来。linux提供了以下两个函数来实现多路IO。
2、select函数
头文件: #include<sys/time.h> #include <sys/types.h> #include <unistd.h> 函数原型:int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 还要搭配以下宏函数来使用 FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd , fd_set *set); FD_ZERO(fd_set *set);
参数说明:
n : 所有的文件描述符中的最大值+1。
readfds:一个结构体指针,里面包含我们需要监测的发生“读”变化文件描述符
writefds:一个结构体指针,里面包含我们需要监测的发生“写”变化文件描述符
exceptfds:一个结构体指针,里面包含我们需要监测的发生“异常”变化文件描述符
timeout:设置时间的结构体
struct timeval{
long tv_sec; //秒数
long tv_usec;//毫秒数
}
FD_CLR(int fd, fd_set *set);:清除文件描述符集合中的一个fd
FD_SET(int fd , fd_set *set); :向文件描述符集合中添加一个fd
FD_ISSET(int fd, fd_set *set); :通过这个宏的返回值来判断哪一个文件出于”就绪”状态,可以来操作此文件。
FD_ZERO(fd_set *set); :清空文件描述符集合
应用举例:
/* 以下代码是读标准输入设备中的数据 */#include <stdio.h>#include <sys/time.h>#include <unistd.h>#define TIMEOUT 5#define BUF_LEN 1024int main(int argc, char const *argv[]){ struct timeval tv; //设置时间的结构体 fd_set readfds; //文件描述符集合 int ret ; FD_ZERO(&readfds); //清空文件描述符集合 FD_SET(STDIN_FILENO, &readfds);// 将文件描述符(标准输入:STDIN_FILENO)添加到集合中去 /* 通过结构体来设置select 等待时间 */ tv.tv_sec = 5; //秒 tv.tv_usec = 0; //微秒 ret = select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv); if(-1 == ret ) { perror("select"); return 1; } else if (ret == 0) //超出时间5s { printf("%d seconds elapsed.Nothing input!\n",TIMEOUT); return 0; } char buf[BUF_LEN+1]; int len; if( FD_ISSET(STDIN_FILENO, &readfds) )//如果监测到有东西输入 { len = read(STDIN_FILENO, buf, BUF_LEN); if(-1 == len) { perror("read"); return 1; } else if (len != 0) { buf[len] = '\0'; printf("read:%s\n", buf); /* code */ } return 0; } fprintf(stderr, "This should not happen!\n"); return 0;}
3、poll函数
头文件:#include<sys/poll.h>函数原型:int poll(struct pollfd *fds, unsigned int nfds, int timeout);
参数说明:
fds : 一个包含多个文件描述pollfd结构体的数组指针
struct pollfd{
int fd; //文件描述符
short events; //要监测的事件
short revents; //需要返回观察的事件
}
其中:events的可选项为
POLLIN : 没有数据可读
POLLRDNORM: 有正常的数据可读
POLLRDBAND :有优先的数据可读
POLLPRI :有高优先级的数据可读
POLLOU : 写操作不会阻塞
POLLWRNORM:写正常数据不会阻塞
POLLBAND : 写优先数据不会阻塞
POLLMSG : 有一个SIGPOLL消息可用
nfds : fds数组中有多少个结构体,fds也就是数组的大小
timeout : 设置时间,同select一样,不过这里的单位是毫秒
应用举例:
//以下程序使用poll函数实现监测标准输入,同select.c文件实现的功能是一样#include <sys/poll.h>#include <stdio.h>#include <unistd.h>#define TIMEOUT 5000 //5000msint main(int argc, char const *argv[]){ struct pollfd fds[1]; int ret; fds[0].fd = STDIN_FILENO; //设置文件描述符 fds[0].events = POLLIN|POLLPRI; //设置读写方式:没有可读事件或者有高优先级数据可读 ret = poll(fds, 1 , TIMEOUT); if(-1 == ret) { perror("poll"); return 1; } else if (0 == ret) //超时 { printf("\n%d seconds elapsed.\n",TIMEOUT); return 0; /* code */ } char buf[100]; int len; if(fds[0].revents & POLLIN) { len = read(STDIN_FILENO, buf, 100); if(-1 == len) { perror("read"); return 1; } else if (len != 0) { buf[len] = '\0'; printf("read:%s\n", buf); return 0; } } printf("Noting\n"); return 0;}
注:由于本人也是刚接触这个,里面不免会有一些错误,请批判接受。上面只是这两个函数最基本的应用举例,对于更复杂的应用,请自行查阅相关资料。
- 多路IO复用 select 和 poll 函数简介
- 第六章 IO复用:select和poll函数
- IO复用: select 和poll 到epoll
- IO复用: select 和poll 到epoll
- Linux IO复用--select()和poll()
- select和poll函数
- select poll 和 epoll简介
- I/O复用:Select和Poll函数
- I/O复用 select和poll函数
- I/O复用:select和poll函数
- poll函数和select函数
- IO复用:poll函数
- IO复用函数select poll epoll
- select和poll函数讲解
- IO模型和Select/Poll/Epoll解析
- select、poll、epoll三组IO复用
- IO复用,select、poll、epoll综述
- UNPv1第六章:IO复用select&poll
- 周立功A3352-W128LI内核编译
- 2016多校训练Contest5: 1004 How Many Triangles hdu5784
- UVA11927
- 循环链表
- XML的查询
- 多路IO复用 select 和 poll 函数简介
- andorid基础之预备讲义
- ZZULIOJ-1894-985的方格难题(动态规划)
- uva 10652 Board Wrapping 凸包
- activiti 流程走向异常 会签节点变量赋值为空问题
- 设置器与访问器。
- 131.Which naming method uses the tnsnames.ora file to store the connect descriptor used by the clien
- 替换空格
- 剖析并利用Visual Studio Code在Mac上编译、调试c#程序 集成到Unity3D