fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
再强调一下,以上操作只对对应的文件描述符有意义;对磁盘文件的文件描述符做此设置总会成功,但是会直接被忽略 。
这时,BIO和NIO的区别是什么呢?
在BIO模式下,调用read,如果发现没数据已经到达,就会Block住 。
在NIO模式下,调用read,如果发现没数据已经到达,就会立刻返回-1, 并且errno被设为 。
在有些文档中写的是会返回 。实际上,在Linux下和是一样的,即#
于是,一段NIO的代码,大概就可以写成这个样子 。
struct timespec sleep_interval{.tv_sec = 0, .tv_nsec = 1000};
ssize_t nbytes;
while (1) {
/* 尝试读取 */
if ((nbytes = read(fd, buf, sizeof(buf))) < 0) {
if (errno == EAGAIN) { // 没数据到
perror("nothing can be read");
} else {
perror("fatal error");
exit(EXIT_FAILURE);
}
} else { // 有数据
process_data(buf, nbytes);
}
// 处理其他事情,做完了就等一会,再尝试
nanosleep(sleep_interval, NULL);
}
这段代码很容易理解,就是轮询,不断的尝试有没有数据到达,有了就处理,没有(得到或者)就等一小会再试 。这比之前BIO好多了,起码程序不会被卡死了 。
但这样会带来两个新问题:
要是操作系统能一口气告诉程序,哪些数据到了就好了 。
于是IO多路复用被搞出来解决这个问题 。
IO多路复用
IO多路复用(IO ) 是这么一种机制:程序注册一组文件描述符给操作系统,表示“我要监视这些fd是否有IO事件发生,有了就告诉程序处理” 。
IO多路复用是要和NIO一起使用的 。尽管在操作系统级别,NIO和IO多路复用是两个相对独立的事情 。NIO仅仅是指IO API总是能立刻返回,不会被;而IO多路复用仅仅是操作系统提供的一种便利的通知机制 。操作系统并不会强制这俩必须得一起用——你可以用NIO,但不用IO多路复用,就像上一节中的代码;也可以只用IO多路复用 + BIO,这时效果还是当前线程被卡住 。但是,IO多路复用和NIO是要配合一起使用才有实际意义 。因此,在使用IO多路复用之前,请总是先把fd设为 。
对IO多路复用,还存在一些常见的误解,比如:
操作系统级别提供了一些接口来支持IO多路复用,最老掉牙的是和poll 。
长这样:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- 个人信息安全影响评估 范围
- java的组件和事件处理 JAVA实现简单的文本文件
- 什么是DFT?FT、FS、DTFT、DFS、DFT的关系
- TTY设备驱动结构
- 上 编写Linux网络设备驱动
- 个人总结 Flume基础知识
- MacOS 安装Hadoop3.1.1教程
- 直方图中最大矩形面积
- 李白中了汪伦的计却跟汪伦更好了?
- 如不才可自取:刘备托孤真有心让位诸葛亮吗?