linux -- read(), write()

read()函数  

2011-03-23 16:28:37|  分类: linux |  标签: |字号 订阅


read
函数从打开的设备或文件中读取数据。

#include <unistd.h>    
ssize_t read(int fd, void *buf, size_t count);  
返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
参数
count
是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1。注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。
read函数返回时,返回值说明了buf中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count,例如:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0。

从终端设备读,通常以行为单位,读到换行符就返回了。

从网络读,根据不同的传输层协议和内核缓存机制,返回值可能小于请求的字节数,后面socket编程部分会详细讲解。


write
函数向打开的设备或文件中写数据。

#include <unistd.h>   
ssize_t write(int fd, const void *buf, size_t count);  
返回值:成功返回写入的字节数,出错返回-1并设置errno写常规文件时,write的返回值通常等于请求写的字节数
count,而向终端设备或网络写则不一定。

读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。同样,写常规文件是不会阻塞的,而向终端设备或网络写则不一定。

现在明确一下阻塞(Block)这个概念。当进程调用一个阻塞的系统函数时,该进程被置于睡眠(Sleep)状态,这时内核调度其它进程运行,直到该进程等待的事件发生了(比如网络上接收到数据包,或者调用sleep指定的睡眠时间到了)它才有可能继续运行。与睡眠状态相对的是运行(Running)状态,在Linux内核中,处于运行状态的进程分为两种情况:


正在被调度执行。CPU处于该进程的上下文环境中,程序计数器(eip)里保存着该进程的指令地址,通用寄存器里保存着该进程运算过程的中间结果,正在执行该进程的指令,正在读写该进程的地址空间。


就绪状态。该进程不需要等待什么事件发生,随时都可以执行,但CPU暂时还在执行另一个进程,所以该进程在一个就绪队列中等待被内核调度。系统中可能同时有多个就绪的进程,那么该调度谁执行呢?内核的调度算法是基于优先级和时间片的,而且会根据每个进程的运行情况动态调整它的优先级和时间片,让每个进程都能比较公平地得到机会执行,同时要兼顾用户体验,不能让和用户交互的进程响应太慢。


下面这个小程序从终端读数据再写回终端。


例 28.2. 阻塞读终端


#include <unistd.h>  
#include <stdlib.h>    
int main(void)  {
   char buf[10];
   int n;
   n = read(STDIN_FILENO, buf, 10);
   if (n < 0) {
    perror("read STDIN_FILENO");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   return 0;  }


执行结果如下:

$ ./a.out   hello(回车)  hello  
$ ./a.out   hello world(回车)  hello 
worl$ d  bash: d: command not found

第一次执行a.out的结果很正常,而第二次执行的过程有点特殊,现在分析一下:


Shell进程创建a.out进程,a.out进程开始执行,而Shell进程睡眠等待a.out进程退出。



a.out调用read时睡眠等待,直到终端设备输入了换行符才从read返回,read只读走10个字符,剩下的字符仍然保存在内核的终端设备输入缓冲区中。


a.out
进程打印并退出,这时Shell进程恢复运行,Shell继续从终端读取用户输入的命令,于是读走了终端设备输入缓冲区中剩下的字符d和换行符,把它当成一条命令解释执行,结果发现执行不了,没有d这个命令。


如果在open一个设备时指定了O_NONBLOCK标志,read/write就不会阻塞。以read为例,如果设备暂时没有数据可读就返回-1,同时置errno为EWOULDBLOCK(或者EAGAIN,这两个宏定义的值相同),表示本来应该阻塞在这里(would block,虚拟语气),事实上并没有阻塞而是直接返回错误,调用者应该试着再读一次(again)。这种行为方式称为轮询(Poll),调用者只是查询一下,而不是阻塞在这里死等,这样可以同时监视多个设备:

while(1) {
非阻塞read(设备1);
if(设备1有数据到达)
  处理数据;
非阻塞read(设备2);
if(设备2有数据到达)
  处理数据;
...
}

如果
read(设备1)
是阻塞的,那么只要设备1没有数据到达就会一直阻塞在设备1的
read
调用上,即使设备2有数据到达也不能处理,使用非阻塞I/O就可以避免设备2得不到及时处理。

非阻塞I/O有一个缺点,如果所有设备都一直没有数据到达,调用者需要反复查询做无用功,如果阻塞在那里,操作系统可以调度别的进程执行,就不会做无用功了。在使用非阻塞I/O时,通常不会在一个while循环中一直不停地查询(这称为Tight Loop),而是每延迟等待一会儿来查询一下,以免做太多无用功,在延迟等待的时候可以调度其它进程执行。

while(1) {
   非阻塞read(设备1);
   if(设备1有数据到达)    处理数据;
   非阻塞read(设备2);
   if(设备2有数据到达)    处理数据;
   ...   sleep(n);
  }

这样做的问题是,设备1有数据到达时可能不能及时处理,最长需延迟n秒才能处理,而且反复查询还是做了很多无用功。以后要学习的select(2)函数可以阻塞地同时监视多个设备,还可以设定阻塞等待的超时时间,从而圆满地解决了这个问题。

以下是一个非阻塞I/O的例子。目前我们学过的可能引起阻塞的设备只有终端,所以我们用终端来做这个实验。程序开始执行时在0、1、2文件描述符上自动打开的文件就是终端,但是没有O_NONBLOCK标志。所以就像例 28.2 “阻塞读终端”一样,读标准输入是阻塞的。我们可以重新打开一遍设备文件/dev/tty(表示当前终端),在打开时指定
O_NONBLOCK标志。


例 28.3. 非阻塞读终端


#include <unistd.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <string.h>  
#include <stdlib.h>    
#define MSG_TRY "try again\n"    
int main(void)  {
   char buf[10];
   int fd, n;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   }
  tryagain:
   n = read(fd, buf, 10);
   if (n < 0) {
    if (errno == EAGAIN) {
     sleep(1);
     write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
     goto tryagain;
    }
     perror("read /dev/tty");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

以下是用非阻塞I/O实现等待超时的例子。既保证了超时退出的逻辑又保证了有数据到达时处理延迟较小。


例 28.4. 非阻塞读终端和等待超时


#include <unistd.h> 
#include <fcntl.h>  
#include <errno.h> 
#include <string.h> 
#include <stdlib.h>   
#define MSG_TRY "try again\n"  
#define MSG_TIMEOUT "timeout\n"    
int main(void)  {
   char buf[10];
   int fd, n, i;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   } 
  for(i=0; i<5; i++) {
    n = read(fd, buf, 10);
    if(n>=0)     break;
    if(errno!=EAGAIN) {
     perror("read /dev/tty");
     exit(1); 
   } 
   sleep(1);
    write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
   } 
  if(i==5)
     write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT));
  else 
    write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

转载于:https://www.cnblogs.com/tianzhiyi/p/5430575.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458767.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jquery的$.extend、$.fn.extend、 jQuery.extend( target, object1, [objectN])作用及区别

jQuery为开发插件提拱了两个方法&#xff0c;分别是&#xff1a; jQuery.fn.extend();jQuery.extend(); 虽然 javascript 没有明确的类的概念&#xff0c;但是用类来理解它&#xff0c;会更方便。 jQuery便是一个封装得非常好的类&#xff0c;比如我们用 语句 $("#btn1&…

CATia对计算机配置要求,【2人回答】求CATIA对电脑的详细配置要求-3D溜溜网

回答&#xff1a;1、内存要求在32G和64G之间。2、硬盘要求选择7200转机械硬盘&#xff0c;4k以上分辨&#xff0c;就选择SSD固态硬盘。3、CPU要求睿频在4.1GHZ以上&#xff0c;核心在6和8核之间。4、显卡要求显存在6GB和11GB之间&#xff0c;位宽要求在192bit和384bit之间。5、…

如何制作自动更新程序?

原文出自&#xff1a;http://blog.csdn.net/metaphysis/article/details/18866631 如何制作自动更新程序&#xff1f; [版权所有 邱秋 2014 metaphysisyeah.net, 转载请注明出处] 最近为单位写了一个C/S结构的软件&#xff0c;这个软件是工作在单位的局域网内的。为了减轻为程序…

包含JS交互的混淆出错

2019独角兽企业重金招聘Python工程师标准>>> 小上司离职&#xff0c;我接手他负责的项目&#xff0c;进行版本更新的时候&#xff0c;在生成jar包测试的时候&#xff0c;点击按钮没有反应&#xff0c;页面是webview&#xff0c;按钮则是与js交互&#xff0c;logcat打…

计算机常用代码大全,常用电脑命令大全【图文】

导语 &#xff1a;电脑&#xff0c;这个在前几年貌似还离我们非常遥远的词汇&#xff0c;现在随着信息化社会的不断发展&#xff0c;已经走进了我们的千家万户。现在每一家新 装修 &#xff0c;它都作为一种必备的家用电器来使用。由此可见电脑对我们 现代 人的重要性。但电脑毕…

细数技术指标-[转载]

技术指标类别庞杂&#xff0c;要一一学全&#xff0c;基本不可能&#xff0c;也没有这个必要。我们只要掌握几个常用的指标&#xff0c;了解它们的原理&#xff0c;从而举一反三&#xff0c;就足够了。其实任何一种技术指标都是从形态、价格、量、时间这四项出发的&#xff0c;…

[javaSE] 看博客学习java并发编程

共享性 多线程操作同一个数据&#xff0c;产生线程安全问题 新建一个类ShareData 设计一个int 型的成员变量count 设计一个成员方法addCount()&#xff0c;把count变量 在main函数中开启多个线程操作这个成员变量&#xff0c;在main函数里 获取ShareData对象&#xff0c;new 出…

GetProcAddress() LoadLibrary() DLL

GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。 函数原型&#xff1a; FARPROC GetProcAddress( HMODULE hModule, // DLL模块句柄 LPCSTR lpProcName // 函数名 ); 参数&#xff1a; hModule [in] 包含此函数的DLL模块的句柄。LoadLibrary、AfxLoadLibrary…

小学计算机输入法主题教研设计,《拼音输入法》教学设计.doc

10.拼音输入法【教材分析】《拼音输入法》是浙江摄影出版社出版的新版《小学信息技术》三年级下册第三单元第10课。信息技术是一门技能课&#xff0c;学以致用是技能课的教学目的&#xff0c;相对来说&#xff0c;在小学生的学习和生活中&#xff0c;用到这项技能的地方还比较少…

图论测试题(一)第一题:longest

第一题&#xff1a;longest 乌托邦有n个城市&#xff0c;某些城市之间有公路连接。任意两个城市都可以通过公路直接或者间接到达&#xff0c;并且任意两个城市之间有且仅有一条路径&#xff08;What does this imply? A tree!&#xff09;。 每条公路都有自己的长度&#xff0…

RTC实时时钟驱动

RTC&#xff08;Real-Time Clock)实时时钟为操作系统提供了一个可靠的时间&#xff0c;并且在断电的情况下&#xff0c;RTC实时时钟也可以通过电池供电&#xff0c;一直运行下去。 RTC通过STRB/LDRB这两个ARM指令向CPU传送8位数据&#xff08;BCD码&#xff09;。数据包括秒&am…

Compass样式重置

1. 全局样式重置 main.scss文件插入 import "compass/reset"; 对应的生成css为 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, sa…

计算机表格复制粘贴后不变,excel表格复制粘贴后格式不变

Excel使用过程中经常需要将一个表格内容复制粘贴到其他表格中去。如果原始表格设置了行高和列宽&#xff0c;选中要复制的区域复制后&#xff0c;当在其他表格选择一个单元格进行粘贴时&#xff0c;行高和列宽就都变了。下面介绍excel表格复制粘贴后格式不变的操作方法。excel表…

C++ Primer章课后编程问题

1、代码#include<iostream> int main() {using namespace std;int num1;int num2;int total0;cout << "请输入開始数字\n";cin >> num1;cout << "请输入结束数字\n";cin >> num2;for (num1; num1<num2; num1)total num1…

vps搭建网站服务器,vps如何架设网站服务器

弹性云服务器 ECS弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器&#xff0c;帮助用户打造可靠、安全、灵活、高效的应用环境&#xff0c;确保服务持久稳定运行&#xff0c;提升运维效率三年低至5折&#xff0c;多种配置可选了解详情手工部署D…

vs 常见问题汇总

vs添加对dll的引用 我们在使用vs进行开发调试的时候经常会遇到一个问题&#xff0c;就是当我们的主工程引用到其他工程更新的dll&#xff08;我们经常采用copy到工程目录的方法&#xff09;、亦或者当我们的多个工程引用到同一个dll文件的时候&#xff0c;我们怎么来配置&#…

斯柯达柯珞克显示服务器错误,斯柯达柯珞克原来还有四驱的版本,不信你看!...

▶有望推出四驱版本▶专利图已经曝光▶外观没有变化斯柯达柯珞克大家应该不会特别陌生&#xff0c;虽然它在前两个月才正式上市&#xff0c;不过作为一款合资的紧凑型SUV来说&#xff0c;它的关注度还是不错的。销量上&#xff0c;4月份交出了2668辆的成绩&#xff0c;虽然还不…

javascript实例——鼠标特效篇(包含2个实例)

鼠标是现在电脑的基本配置之一&#xff0c;也是最常用的输入命令的工具之一。本文将将一些与鼠标有关系的特效。 1、跟随鼠标移动的彩色星星 如题&#xff0c;会根据鼠标的移动而移动&#xff0c;并在鼠标周围随机来回移动&#xff0c;让人感觉在放大缩小。根据书上的代码做了一…

Perforce使用指南_forP4V

第一章 前言 Perforce SCM System是一款构建于可伸缩客户/服务器结构之上的软件配置管理工具。仅仅应用 TCP/IP&#xff0c;开发人员就能够通过多种Perforce客户端&#xff08;几种平台的GUI、WEB、或命令行&#xff09;访问 Perforce服务器。Perforce能够被快速和容易地部署…

sql语句示例

sql语句示例&#xff1a; 选区指定的列 select 图书编号,图书名称 from 图书查询全部信息 select * from 图书查询信息之后更改所获得的列的名称 select 姓名 as 用户名, 电话 as 联系电话 from 用户也可以这样 select 用户名姓名,联系电话电话 from 用户对某些列进行计筭后在显…