设为首页 加入收藏

TOP

11.5.4 _read
2013-10-07 00:46:03 来源: 作者: 【 】 浏览:67
Tags:11.5.4 _read

11.5.4  _read

_read的代码位于crt/src/read.c。在省略了一部分无关紧要的代码之后,其内容如下:

fread -> fread_s -> _fread_nolock_s -> _read:
int __cdecl _read (int fh, void *buf, unsigned cnt)
{
int bytes_read;                 /* number of bytes read */
char *buffer;                   /* buffer to read to */
int os_read;                    /* bytes read on OS call */
char *p, *q;                    /* pointers into buffer */
char peekchr;                   /* peek-ahead character */
ULONG filepos;                  /* file position after seek */
ULONG dosretval;                /* o.s. return value */
    bytes_read = 0;                 /* nothing read yet */
buffer = buf;
这部分是_read函数的参数、局部变量和初始化部分。下面的代码处理一个单字节缓冲:
if ((_osfile(fh) & (FPIPE|FDEV)) && _pipech(fh) != LF) 
{
*buffer++ = _pipech(fh);
++bytes_read;
--cnt;
_pipech(fh) = LF;        
}
if中的判断语句使得这段代码仅对设备和管道文件有效。对于设备和管道文件,ioinfo结构提供了一个单字节缓冲pipech字段用于处理一些特殊情况。宏_pipech返回这一字段:
#define _pipech(i)  ( _pioinfo(i)->pipech )

pipech字段的值等于LF(即字符\n)的时候表明该缓冲无效,这样设计的原因是pipech的用途导致它永远不会被赋值为LF。我们将在稍后的部分里详细讨论这一话题。

_read函数在每次读取管道和设备数据的时候必须先检查pipech,以免漏掉一个字节。在处理完这个单字节缓冲之后,接下来的内容是实际的文件读取部分:

if ( !ReadFile( (HANDLE)_osfhnd(fh), buffer, cnt, (LPDWORD)&os_read, NULL ) )
{
if ( (dosretval = GetLastError()) ==
ERROR_ACCESS_DENIED )        
{
errno = EBADF;
_doserrno = dosretval;
return -1;
}
else if ( dosretval == ERROR_BROKEN_PIPE )
{
return 0;
}
else
{
_dosmaperr(dosretval);
return -1;
}
}
ReadFile是一个Windows API函数,由Windows系统提供,作用和_read类似,用于从文件里读取数据。在这里我们可以看到ReadFile接管了_read的第一个职责。在ReadFile返回之后,_read要检查其返回值。值得注意的是,Windows使用的函数返回值系统和crt使用的返回值系统是不同的,例如Windows使用ERROR_INVALID_PARAMETER(87)表示无效的参数,而CRT则用EBADF(9) 表示相同的信息。因此当ReadFile返回了错误信息之后,_read要把这个信息翻译为crt所使用的版本。_dosmaperr就是做这件工作的函数。在这里就不详细说明了。
【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇11.5.5 文本换行 下一篇11.5.6 fread回顾

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: