linux c编程:非阻塞I/O
通常来说,从普通文件读数据,无论你是采用 fscanf,fgets 也好,read 也好,一定会在有限的时间内返回。但是如果你从设备,比如终端(标准输入设备)读数据,只要没有遇到换行符(‘\n’),read 一定会“堵”在那而不返回。还有比如从网络读数据,如果网络一直没有数据到来,read 函数也会一直堵在那而不返回。
read 的这种行为,称之为 block,一旦发生 block,本进程将会被操作系统投入睡眠,直到等待的事件发生了(比如有数据到来),进程才会被唤醒。
系统调用 write 同样有可能被阻塞,比如向网络写入数据,如果对方一直不接收,本端的缓冲区一旦被写满,就会被阻塞。
比如下面的程序
int main() {
char buf[10];
int len;
while(1) {
// STDIN_FILENO 是标准输入的描述符,它的值是 0. STDOUT_FILENO 是标准输出的描述符,它的值是 1.
len = read(STDIN_FILENO, buf, 10);
write(STDOUT_FILENO, buf, len);
}
return 0;
}
gcc –o main.out main.c
./main.out
如果不向终端输入数据,程序将永远阻塞在read系统调用处。要规避这个问题,我们就需要用到非阻塞的IO。
对于一个给定的描述符有两种方法对其指定非阻塞I/O:
1) 如果调用open获得描述符,则可指定O_NONBLOCK标志
2) 对于已打开的一个描述符,则可调用fcntl,由该函数打开O_NONBLOCK文件状态标志。
程序如下:
set_f1是设置读取的方式为非阻塞,clr_f1则是清除非阻塞的方式
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
void set_f1(int fd,int flags){
int val;
if ((val=fcntl(fd,F_GETFL,0)) < 0)
printf("fcntl F_GETFL
error");
val|=flags;
if (fcntl(fd,F_SETFL,val) < 0)
printf("fcntl F_sETFL
error");
}
void clr_f1(int fd,int flags){
int val;
if ((val=fcntl(fd,F_GETFL,0)) < 0)
printf("fcntl F_GETFL
error");
val&=~flags;
if (fcntl(fd,F_SETFL,val) < 0)
printf("fcntl F_sETFL
error");
}
char buf[50000];
int main()
{
int ntowrite,nwrite;
char *ptr;
ntowrite=read(STDIN_FILENO,buf,sizeof(buf));
fprintf(stderr,"read %d bytes\n",ntowrite);
set_f1(STDOUT_FILENO,O_NONBLOCK);
ptr=buf;
while(ntowrite > 0){
errno=0;
nwrite=write(STDOUT_FILENO,ptr,ntowrite);
fprintf(stderr,"nwrite=%d,errno=%d\n",nwrite,errno);
if(nwrite > 0){
ptr+=nwrite;
ntowrite-=nwrite;
}
}
clr_f1(STDOUT_FILENO,O_NONBLOCK);
return 0;
}
若标准输出是普通文件,则可以期望write只执行一次
root@maple-VirtualBox:/home/maple/codeblock_prj/func_test#
./main.out < /etc/services > temp.file
read 19605 bytes
nwrite=19605,errno=0
root@maple-VirtualBox:/home/maple/codeblock_prj/func_test# ls -al temp.file
-rw-r--r-- 1 root root 19605 8月 12 15:33
temp.file
但是,如果标准输出是终端。则有时会返回错误。
root@maple-VirtualBox:/home/maple/codeblock_prj/func_test#
cat stderr.out
read 19605 bytes
nwrite=14907,errno=0
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=4698,errno=0
程序发出了多个write调用,但是只有部分真正输出了数据。其他的都只返回了错误。这种形式的循环成为轮询。在多用户系统上会浪费CPU时间。
linux c编程:非阻塞I/O的更多相关文章
- boot asio 非阻塞同步编程---非阻塞的accept和receive。
boot asio 非阻塞同步编程---非阻塞的accept和receive. 客户端编程: #include<boost/timer.hpp> #include <iostream ...
- linux 客户端 Socket 非阻塞connect编程
开发测试环境:虚拟机CentOS,windows网络调试助手 非阻塞模式有3种用途 1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...
- linux网络编程中阻塞和非阻塞socket的区别
读操作 对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返 回.当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数.当 ...
- socket编程 —— 非阻塞socket (转)---例子已上传至文件中
在上一篇文章 <socket编程——一个简单的例子> http://blog.csdn.net/wind19/archive/2011/01/21/6156339.aspx 中写了一个简单 ...
- UNIX网络编程——非阻塞connect:时间获取客户程序
#include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) ...
- python 并发编程 非阻塞IO模型
非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图 ...
- UNIX网络编程-非阻塞connect和非阻塞accept
1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长 ...
- UNIX网络编程——非阻塞accept
当有一个已完成的连接准备好被accept时,select将作为可读描述符返回该连接的监听套接字.因此,如果我们使用select在某个监听套接字上等待一个外来连接,那就没有必要把监听套接字设置为非阻塞, ...
- UNIX网络编程——非阻塞connect: Web客户程序
非阻塞的connect的实现例子出自Netscape的Web客户程序.客户先建立一个与某个Web服务器的HTTP连接,再获取一个主页.该主页往往含有多个对于其他网页的引用.客户可以使用非阻塞conne ...
- UNIX网络编程——非阻塞connect
当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...
随机推荐
- iPhone手机解锁效果&&自定义滚动条&&拖拽--Clone&&窗口拖拽(改变大小/最小化/最大化/还原/关闭)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- quick-cocos2d-x教程9:实例之加上背景图片
在梳理完quick-cocos2d-x框架的各个文件夹后,我们開始我们的实例教程,在helloworld后面.加上一张图片,lua编辑器,我用的lua editor.还不错. 我们首先还是參照教程.创 ...
- JavaScript创建块级作用域
1.JavaScript创建块级作用域 (1)方法一:ES6 (2)方法二:闭包 2.示例 <!DOCTYPE html> <html lang="zh"> ...
- C# : 资源文件(多用于处理国际化)
1.建立Resource文件夹,添加资源文件 处理国际化的问题,我们可以添加多个资源文件,如下就是添加一个中文的,一个英文的. 2.向其中添加键值对. 3.取值 CultureInfo uiCultu ...
- Kafka备忘
官网 http://kafka.apache.org/ 多生产者多消费者 多topic和多分区 多消费者组.每组中消息不能重复消费,组间不影响 启动 RunKafka(){ cd $kafka_hom ...
- 多trac的安装和配置
其他相关网页: trac+svn: http://wenku.baidu.com/view/84389a81ec3a87c24028c43f.html apache(GCI):http://hi.ba ...
- asp.net core mvc视频A:笔记3-5.视图数据共享之TempData
前几节讲的都是单页面数据共享,从本节开始讲跨页面数据共享 创建项目3.5,新建控制器 代码 控制器 设置TempData 另一个视图中读取TempData数据 运行 此时如果刷新页面,页面中的内容“张 ...
- 转Postman请求Https接口
转自:https://blog.csdn.net/ONS_cukuyo/article/details/79172242 单向认证 像平常一样访问就行,无需做任何处理,只需要把http://变成htt ...
- Machine Learning——Unsupervised Learning(机器学习之非监督学习)
前面,我们提到了监督学习,在机器学习中,与之对应的是非监督学习.无监督学习的问题是,在未加标签的数据中,试图找到隐藏的结构.因为提供给学习者的实例是未标记的,因此没有错误或报酬信号来评估潜在的解决方案 ...
- Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.2(转)
转自 http://bbs.weiphone.com/read-htm-tid-6939481.html 继续更新到7.3.2的破解.只是升级了下secureCRT到7.3.2,方法还是不变 相信很多 ...