select函数与stdio混用的不良后果 (转)
出自:http://www.cppblog.com/mysileng/archive/2013/01/15/197284.html
今天在看UNP6.5节,学习到了select与stdio混用的后果。特此进程实验一番。再实验之前需明确一下几点:
1.stdio流的i/o函数 与 系统i/o函数不同。stdio流函数在用户空间和内核都有缓冲,系统i/o函数只在内核有缓冲,用户空间没有。
2.stdio流的i/o函数缓冲机制:在面对文件时候用的是全缓冲,面对设备的时候用的行缓冲。(等下试验用的是键盘和屏幕),所以实验用的stdio函数采用行行缓冲。
3.select函数对于某一个描述符是否准备好可读可写,是对内核缓冲区中的数据是否达到某一个最低标准,而不是用户缓冲区。也就是说select函数不知道用户缓冲区的存在。
首先写了一个系统i/o函数 简单的select函数程序:
程序给select函数只设置的键盘的描述符。也就是说如果键盘的描述符准备好了就不再阻塞。但是这里有一个问题,解除阻塞后,我们最多只从内核缓冲区读3个字节,这个时候就会有两个情况:
(1)内核空间本来存储的数据就小于等于3个字节,全被读走。那下次再次调用select函数,应该肯定会阻塞的,因为键盘输入的内核缓冲区已经没有数据了。
情况如下(内核空间只有3个字节:1 2 \n):
(2)如果内核空间的数据多余3个字节,但是因为最多只能读3个字节,就必将导致内核中有数据读不完。那么下次再遇到select函数的时候是否会阻塞呢?
情况见下:
当我们输入5个字符时候(1 2 3 4 \n),第一次read掉3个字符,内核空间还剩下2个字符,然后再次碰到select函数,默认情况下如果键盘内核空间字符数大于1,select是不会阻塞键盘描述符的。结果也印证了,又read了2个字节,并没有堵塞。
综上所述select是可以看见内核空间的缓冲区的。那到底能不能看见用户空间缓冲区呢?我们换成stdio流的i/o函数继续实验。
--------------------------------------------------------------------
stdio流的i/o函数使用select函数的程序如下:
程序用stdio流的getc函数从键盘读数据,运行结果如下:
我们输入5个字符(1 2 3 4 \n),结果只输出了1个字符,然后就阻塞了。我们分析一下,首先输入5个字符,这5个字符被放入用户缓冲区,因为最后一个是换行符并且stdio面对设备使用行缓冲机制,所以这5个字符马上接着被从用户缓冲区刷入内核缓冲区。然后调用select函数,select函数发现内核空间中有数据,于是不阻塞返回。接着getc函数从用户空间输出缓冲区取一个字符,因为用户空间输出缓冲区没有数据,于是把内核空间的数据调入一行给用户空间输出缓冲区,然后getc返回。接着又碰上select函数,因为内核缓冲空间的数据已经被放入用户空间输出缓冲区了,所以内核缓冲没有数据,那么select认为键盘没有准备好,所以阻塞。虽然阻塞了,但需要注意的时候这个时候,用户空间是有4个字符数据的,被select函数无视了。
接下来假设我们再输入2个字符(1 \n),将会发生什么呢?
输出一对东西,这是怎么回事,我们继续分析。当输入2个字符(1 \n)的时候,内核空间缓冲没有数据,用户空间输出缓冲有4个字符。2个字符根据上一段同样原理,被刷入内核空间缓冲区。select函数被调用,发现有2个字符,于是不阻塞返回。getc函数从用户输出缓冲取出一个字符,打印stardard... --2然后返回。再次循环,调用select函数。关键来了,这里跟上次不一样了。这个时候内核空间的缓冲中还有上次遗留的2个字符,所以依然不阻塞返回,调用getc函数继续打印。。。这里的关键是,getc函数。getc函数在用户输出缓冲中有数据的时候,不会把内核空间缓冲中的数据移入用户空间的输出缓冲,使得内核空间缓冲一直留有数据。这将会持续到用户空间输出缓冲的数据被取完为止。所以上述奇怪的打印结果就可以解释的了。
综上所述,select函数确实是看不见用户空间缓冲的寻在的。
所以如果在使用select函数的时候,要谨慎使用stdio流函数。
select函数与stdio混用的不良后果 (转)的更多相关文章
- select与stdio混合使用的不良后果
参考以下链接自己补充实验:http://www.cppblog.com/mysileng/archive/2013/01/15/197284.aspx?opt=admin int main(int a ...
- select函数实例代码
select函数简解: selct 称之为多路复用IO,使用它可以让程序阻塞在select上,而非实际IO函数上. int select(int nfds, fd_set *readfds, fd_s ...
- select 函数1
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序( ...
- IO复用与select函数
socket select函数的详细讲解 select函数详细用法解析 http://blog.chinaunix.net/uid-21411227-id-1826874.html linu ...
- 异步套接字基础:select函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
参考:[原创]技术系列之 网络模型(三)多路复用模型 select函数 select函数: 系统提供select函数来实现多路复用输入/输出模型.原型: #include <sys/time.h ...
- Linux下select函数的使用
一.Select 函数详细介绍 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv ...
- linux c语言 select函数用法
linux c语言 select函数用法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unis ...
- select函数的介绍和使用
我们所使用的I/O模型一共有五种. 分别为阻塞I/O,非阻塞I/O,I/O复用,信号驱动I/O,异步I/O. 所谓I/O复用就是指管理多个I/O文件描述符,一般会使用(select,poll,epol ...
- UNIX网络编程——select函数的并发限制和 poll 函数应用举例
一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置, ...
随机推荐
- Element表单验证(2)
Element表单验证(2) 上篇讲的是async-validator的基本要素,那么,如何使用到Element中以及怎样优雅地使用,就在本篇. 上篇讲到async-validator由3大部分组成 ...
- 201621123080《Java程序设计》第三周学习总结
Week03-面向对象入门 1. 本周学习总结 2. 书面作业 1.以面向对象方式改造数据结构作业'有理数'(重点) 1.1 截图你主要代码(需要在程序中出现你的学号和姓名)并粘贴程序的git地址. ...
- vue 项目白屏解决方案
在做的项目是使用 vue-cli 脚手架为基础的,只能使用微信浏览器打开的.在某次更新功能代码后,被反馈在一些手机上会出现白屏.经过一番探索,多管齐下解决了问题 白屏可能的原因: es6 代码没有被编 ...
- redis集群监控之Redis-monitor部
为了对以后有可能面临的redis集群监控做准备,这两天在准备这方面的事情,现在将其中的过程记录一下. 首先是“Ronney-Hua”的这篇文章对三中开源监控软件做了对比 文章地址:https://bl ...
- HTTPS的请求与响应
HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfer ...
- Linux学习-SRPM 的使用 : rpmbuild (Optional)
新版的 rpm 已经 将 RPM 与 SRPM 的指令分开了,SRPM 使用的是 rpmbuild 这个指令,而不是 rpm 喔! 利用默认值安装 SRPM 文件 (--rebuid/--recomp ...
- POJ 3241 曼哈顿距离最小生成树 Object Clustering
先上几个资料: 百度文库有详细的分析和证明 cxlove的博客 TopCoder Algorithm Tutorials #include <cstdio> #include <cs ...
- 当列表推导式遇到lambda(匿名函数)
Python这么优雅的语言,我也是醉了...... 事情由一段代码引发,请看: 上述的列表推导式+lambda表达式+for循环,他们碰撞出来的结果搞的人晕头转向,咱们逐步来分析一下他们到底是个什么鬼 ...
- JAVA 基础--开发环境 vscode 搭建
对于使用 Visual Studio Code 的 Java 开发者来说,Language Support for Java(TM) by Red Hat 扩展提供了非常好的语言特性支持,比如智能感知 ...
- php-数据库连接类
<?php class DB{ var $host; var $user; var $pwd; var $dbname; var $conn; function DB($host,$user,$ ...