linux c 非阻塞 键盘,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

#include

#include

#include

#include

#include

#include

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时间。

boot asio 非阻塞同步编程---非阻塞的accept和receive。

boot asio 非阻塞同步编程---非阻塞的accept和receive. 客户端编程: #include #include 

linux 客户端 Socket 非阻塞connect编程

开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...

linux网络编程中阻塞和非阻塞socket的区别

读操作 对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返 回.当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数.当 ...

socket编程 —— 非阻塞socket &lpar;转&rpar;---例子已上传至文件中

在上一篇文章 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&colon; Web客户程序

非阻塞的connect的实现例子出自Netscape的Web客户程序.客户先建立一个与某个Web服务器的HTTP连接,再获取一个主页.该主页往往含有多个对于其他网页的引用.客户可以使用非阻塞conne ...

UNIX网络编程——非阻塞connect

当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...

随机推荐

java web&lpar;六&rpar;多个请求对应一个Servlet

概要: 提交请求的常用方式有两种,get/post , 运行程序后被请求,在加载执行web.xml文件时通过该文件中的映射关系找到即将要执行的Servlet; 而在要执行的Servlet文件中可通过反 ...

小议安卓定位伪造-实战足不出户畅玩Pokemon Go

本文旨在技术探讨故本文不提供工具,正常玩家请勿模仿,游戏中虚拟位置有封号风险 0x00 安卓定位方式归类 要伪造定位首先要摸清定位到底是如何实现的,首先从广义上来区分安卓的定位方式实际上就gps和ne ...

PHP 7&period;1 新特性一览

可空类型主要用于参数类型声明和函数返回值声明.主要的两种形式如下:<?phpfunction answer(): ?int  {   return null; //ok}function ans ...

Load an X509 PEM file into Windows CryptoApi

http://stackoverflow.com/questions/1231178/load-an-x509-pem-file-into-windows-cryptoapi I discovered ...

C&num; Java间进行RSA加密解密交互(二)

原文:C# Java间进行RSA加密解密交互(二) 接着前面一篇文章C# Java间进行RSA加密解密交互,继续探讨这个问题. 在前面,虽然已经实现了C# Java间进行RSA加密解密交互,但是还是与 ...

python3-day4&lpar;装饰器&rpar;

一.基本 第一波 #### def foo():     print 'foo'   foo     #表示是函数 foo()   #表示执行foo函数   #### 第二波 #### def foo ...

向上取整Ceil,向下取整Floor,四舍五入Round

几个数值函数的功能实现: (1)int Ceil(float f) int Ceil(float f) { int integer = (int)f; if (f > (float)intege ...

nefu 462 fib组合

nefu 462 fib组合 (斐波那契数列的通项公式以及推倒过程) 分类: 数学2014-05-21 10:27 190人阅读 评论(0) 收藏 举报 题目链接:http://acm.nefu.ed ...

jQuery匿名函数&dollar;&lpar;function&lpar;&rpar;&lbrace; &rcub;

搬运原地址:https://zhidao.baidu.com/question/473318430.html $(function(){ }实际上是匿名函数.这是JQuery的语法,$表示JQuery ...

PHP到底有多牛?你所知道的网站都在用它

PHP到底有多牛?你所知道的网站都在用它 提起PHP,很多人的第一印象就是网站开发,确实,在网站开发方面,PHP难逢对手,当之无愧是“世界上最好的语言”. 有数据显示,目前全球5000万互联网网站中, ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值