期末作业第十章

系统级I/O

UNIX I/O

在UNIX系统中有一个说法,一切皆文件。所有的I/O设备,如网络、磁盘都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。这种将设备映射为文件的方式,允许UNIX内核引出一个简单、低级的应用接口,称为UNIX I/O,这使得所有的输入和输出都能以一种统一且一致的方式来执行。

  • 打开文件 打开文件操作完成以后才能对文件进行一些列的操作,打开完成过以后会返回一个文件描述符,它在后续对此文件的所有操作中标识这个文件,内核记录有关这个打开文件的所有信息。
  • 改变当前的文件位置。
  • 读写文件
  • 关闭文件 应用完成了对文件的访问之后,就通知内核关闭这个文件,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。进程终止,内核也会关闭所有打开的文件并释放他们的存储器资源
打开和关闭文件

进程是通过调用open函数来打开一个已存在的文件或者创建一个新文件的:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(char *filename, int flags, mode_t mode);

返回,若成功则为新文件描述符,若出错为-1
open函数将filename转化为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符。flags参数指明了进程打算如何访问这个文件:

  • O_RDONLY:只读
  • O_WRONLY:只写
  • O_RDWR:可读可写
mode参数指定了新文件的访问权限位。

在这里插入图片描述

读和写文件

在系统I/O中读写文件用的系统函数为read()和write()函数来执行。

#include <unistd.h>
 
ssize_t read(int fd,void * buf,size_t n);
 
ssize_t write(int fd,void *buf,size_t n);

read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。返回值-1表示一个错误,而返回值0表示EOF。否则,返回值表示的是实际传送的字节数量。而write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。返回值要么为-1要么为写入的字节数目。

/* $begin cpstdin */
#include "csapp.h"
 
int main(void) 
{
    char c;
 
    while(Read(STDIN_FILENO, &c, 1) != 0) 
	Write(STDOUT_FILENO, &c, 1);
    exit(0);
}
/* $end cpstdin */

关于在文件中定位使用的函数为lseek,在I/O库中使用的函数为fseek。
(ps:size_t和ssize_t的区别,前者是unsigned int,而后者是int)

有些情况下,read和write传送的字节比应用程序要求的要少,出现这种情况的原因如下:
  • 读时遇到EOF。此时read返回0来发出EOF信号。
  • 从终端读文本行。如果打开文件是与终端相关联,那么每个read函数将以此传送一个文本行,返回的不足值等于文本行的大小。
  • 读和写网络套接字。可能会出现阻塞现象。
实际上,除了EOF,在读磁盘文件时,将不会遇到不足值,而且在写磁盘文件时,也不会遇到不足值。然而,如果你想创建健壮的网络应用,就必须反复调用read和write处理不足值,直到所有需要的字节都传送完毕。
用RIO包健壮地读写

这个包会处理上面的不足,RIO提供了方便、健壮和高效的I/O。提供了两类不同的函数:

  • 无缓冲的输入输出函数 直接在存储器和文件之间传送数据,没有应用级缓冲,它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。
  • 带缓冲的输入函数
ssize_t rio_readn(int fd,void *usrbuf,size_t n);
 
ssize_t rio_writen(int fd,void *usrbuf,size_t n);

对同一个描述符,可以任意交错地调用rio_readn和rio_writen。一个问本行的末尾都有一个换行符,那么像读取一个文本中的行数怎么办,使用read读取换行符这个方法不是很妥当,可以调用一个包装函数(rio_readineb),它从一个内部读缓冲区拷贝一个文本行,当缓冲区为空时,会自动地调用read重新填满缓冲区。也就是说,这些函数都是缓冲区操作而言的。

标准I/O

标准I/O库将一个打开的文件模型化为一个流。对于一个程序而言,一个流就是一个指向FILE类型的结构的指针。类型为FILE的流是对文件描述符和流缓冲区的抽象。流缓冲区的目的和RIO读缓冲区的一样:就是使开销较高的UNIX I/O系统调用的数量尽可能的小。例如,当第一次调用getc时,库通过调用一次read函数来填充流缓冲区,然后将缓冲区总的第一个字节返回给应用程序。只要缓冲区还有未读的字节,接下来对getc的调用就能直接从流缓冲区得到服务。

I/O使用的抉择方法

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值