Linux select和poll系统调用
来源:互联网 发布:淘宝网售后服务网址 编辑:程序博客网 时间:2024/05/18 00:14
很多时候,我们调用read函数从文件描述符中读取数据时,如果此时恰好没有数据可读,read系统调用势必会阻塞住。同样,当调用write函数时,而没有空间供我们写入,write系统调用也会被阻塞住,直到有空间被写入时。那么在这种情况下我们为了不阻塞我们的程序,就需要检查文件描述符是否可读或可写。
1. select系统调用
首先我们来看一段代码:
参数nfds必须设定为比3个文件描述符集合中的所包含的最大文件描述符还要大1,什么意思呢,假如我们只关注read,而read集合中包含两个文件描述符,它们的值分别为2、3,那么这里nfds就必须设置为大于等于3+1。
参数timeout为超时时间。
使用select系统调用的示例如下:
2. poll系统调用
poll系统调用同select系统调用类似,原型如下:
上面的代码使用poll系统调用修改如下:
1. select系统调用
首先我们来看一段代码:
#include <stdio.h>#include <unistd.h>int main(void){ int bytes_read; char buffer[128]; bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer)); if (buffer[bytes_read - 1] == '\n') buffer[bytes_read - 1] = '\0'; printf("%s\n", buffer); return 0;}
上面这段代码是从标准输入端读取字符并显示出来,如果我们不输入任何字符,那么read函数是会被阻塞的,直到我们输入了任意字符并按了回车键。那么如何避免被阻塞呢,来看select系统调用,原型如下:
#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);参数readfds、writefds、exceptfds都是指向文件描述符的指针,数据类型为fd_set。而readfds是用来检测输入的,writefds是用来检测输出的,exceptfds使用检测是否异常的。有关fd_set通常有四个宏供我们操作:FD_ZERO、FD_SET、FD_CLR、FD_ISSET。
void FD_CLR(int fd, fd_set *set);int FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);FD_ZERO是将fd_set所指向的集合清空,FD_SET是将文件描述符fd添加到fd_set所指向的集合中,FD_CLR是将文件描述符fd从fd_set所指向的集合中移除,而如果文件描述符fd是fd_set所指向的集合中的成员,则FD_ISSET返回true,否则返回false。文件描述符集合有一个最大容量限制,由常量FD_SETSIZE来决定,在Linux上,该常量值为1024。
参数nfds必须设定为比3个文件描述符集合中的所包含的最大文件描述符还要大1,什么意思呢,假如我们只关注read,而read集合中包含两个文件描述符,它们的值分别为2、3,那么这里nfds就必须设置为大于等于3+1。
参数timeout为超时时间。
使用select系统调用的示例如下:
#include <stdio.h>#include <unistd.h>#include <sys/select.h>int main(void){ int bytes_read, ready; char buffer[128]; fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); timeout.tv_sec = 10; timeout.tv_usec = 0; ready = select(STDIN_FILENO+1, &readfds, NULL, NULL, &timeout); if (ready) { bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer)); if (buffer[bytes_read - 1] == '\n') buffer[bytes_read - 1] = '\0'; printf("%s\n", buffer); } else { printf("No data to read\n"); } return 0;}如果没有数据可读,select系统调用也是会被阻塞的,直到超时为止,这里设定是的10秒。如果没有指定timeout参数,则select系统调用会永远阻塞下去。
2. poll系统调用
poll系统调用同select系统调用类似,原型如下:
#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);struct pollfd定义如下:
struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */};参数nfds为fds元素个数。timeout为超时时间,单位为毫秒,如果timeout等于-1,poll系统调用会一直阻塞,如果timeout等于0,则poll系统调用之检测一次并立即退出,如果timeout大于0,则poll系统调用会最多阻塞timeout毫秒,直到数据可读或可写。
上面的代码使用poll系统调用修改如下:
#include <stdio.h>#include <unistd.h>#include <poll.h>int main(void){ int bytes_read, ready; char buffer[128]; struct pollfd readfds; readfds.fd = STDIN_FILENO; readfds.events = POLLIN; ready = poll(&readfds, 1, 10000); if (ready) { bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer)); if (buffer[bytes_read - 1] == '\n') buffer[bytes_read - 1] = '\0'; printf("%s\n", buffer); } else { printf("No data to read\n"); } return 0;}
参考教程:The Linux Programming Interface - A Linux and UNIX System Programming Handbook.pdf
0 0
- Linux select和poll系统调用
- 内核poll和select系统调用的图解(1)-poll系统调用的整体结构图
- 内核poll和select系统调用的图解(1)-poll系统调用的整体结构图
- I/O复用系统调用之select()和poll()
- linux系统调用poll
- Linux的poll和select
- select(poll)系统调用实现解析(一)
- select(poll)系统调用实现解析(二)
- select(poll)系统调用实现解析(三)
- select(poll)系统调用实现解析(二)
- select(poll)系统调用实现解析(一)
- select(poll)系统调用实现解析(二)
- select(poll)系统调用实现解析(三)
- select(poll)系统调用实现解析(一)
- select(poll)系统调用实现解析(三)
- select(poll)系统调用实现解析(二)
- select(poll)系统调用实现解析(一)
- select poll epoll系统调用详细分析
- B. Gerald is into Art
- 28-反射机制-07-反射机制(反射练习)
- 高仿知乎日报(一)
- 推荐ubuntu好用的词典stardict (安装及免费词库下载)
- Android应用程序:简单拨号器
- Linux select和poll系统调用
- 网盘秒传的实现方式
- NOIP2014提高组解方程
- 多线程 - 课程分析
- Manacher算法
- TCP/IP协议三次握手及断开
- mysql当中时间类型是如何存储的
- 28-正则表达式-01-正则表达式(概述)
- python 学习点滴