CSAPP复习之系统级别I/O

系统级别I/O

Unix I/O

基于连接

  • UnixIO:系统调用 open close read write stat

  • 标准IO:f开头 针对文件的stream流

    xscanf xprintf 有格式的

  • RIO:新提出的

Unix IO Overview

  • 文件是字节的序列
    • 描述符
      • 打开文件时,内核返回一个小的非负整数
  • 当前文件位置指针k(seek)
  • 读写
      • 从文件的当前文件位置k复制n个字节到内存
      • 改变k为k+n
      • 在文件位置大于等于文件大小后再执行读操作就会遇到EOF条件(文件末尾并没有显式的EOF符号)
      • 从内存复制n个字节到一个文件
      • 更新k

文件类型

  • 普通文件 DISK里B0,B1…Bm-1
    • 文本文件
    • 二进制文件
  • 目录
    • 包含一组链接的文件
      • 每个链接都将一个文件名映射到一个文件
    • 每个目录至少含两个条目
      • “.” “…”
  • 套接字
  • 管道等此处不讨论
普通文件
  • 文本文件
  • 二进制文件
  • 电脑不知道text和二进制的区别
  • 换行和回车
    • windows和网络用的是回车换行,linux mac是换行
  • 判断脚本文件#!(0x20之前的叫不可打印字符)
目录
  • 目录的组织结构 绝对路径和相对路径

    • . 当前目录 … 上一级目录
  • 当前工作目录

    • include <>是先从系统的库文件找
    • ""是先从当前工作目录找
  • 绝对路径 从root开始 一直到当前文件

  • 相对路径 用.和…

    • 从当前工作目录开始
    • 用…的如果换一台机器就会找不到该文件

打开文件

  • 每个进程被创建时就打开了三个文件
    • stdin stdout stderr
  • open函数
    • 成功返回新文件描述符
      • 返回的描述符总是在进程中当前没有打开的最小描述符
    • 失败返回-1

关闭文件

  • close函数
    • 有返回值 成功返回0 失败返回-1
  • 关闭一个已经被关闭的文件会出错(需要关心)

读取文件

  • read函数
    • 成功返回读的字节数
    • 错误返回-1
      • 返回值是有符号的 sizeof是无符号的
  • 有可能遇到 short counts 不足值 不是一个错误 读取可以少不能多

写文件

  • 与读取类似 只是方向不同

  • 和读取共享当前位置指针

例子
int main(void){
char c;

while(Read(STDIN_FILENO, &c, 1) != 0)
    Write(STDOUT_FILENO, &c, 1);
exit(0);}

先从KB输入到内核的一个buffer之后才由程序去读取

不足值
  • 除了EOF 读写磁盘文件时永远不会遇到不足值

  • 发生情况:

    • 遇见EOF(EOF不是字符 仅仅是当文件大小到头时代表结束)
    • 从终端读文本行
    • 读写网络、硬件套接字时

读取文件元数据

  • 用stat/fstat访问解析
  • 由内核保存

共享文件

  • 内核用三个相关的数据结构来表示打开的文件
    • 每个进程一个 描述符表
      • 表项是进程打开的文件描述符
        • 每个打开的描述符表项指向文件表中的一个表项
    • 所有进程共享 文件表
      • 表项组成
        • 文件位置
        • refcnt—本质上是为了资源回收的
        • 指向v-node表中表项的指针
    • 所有进程共享 v-node表
      • 表项包含stat结构的大多数信息
        • st_size
        • st_mode
fork
  • fork复制描述符表
  • 描述符表中的指针指向相同的文件表的位置
  • referencecount增加

IO重定向

  • dup2 int dup2(int oldfd, int newfd);
  • 把描述符表项oldfd覆盖到描述符表项newfd

标准IO

  • 文件被模型化为流
  • 流缓冲区
  • 流 = 指向FILE类型的一个指针

buffered IO

  • 区分binary 和 text(unformatted formatted)
  • 标准IO使用bufferedIO
    • 使开销高的linuxIO调用次数尽可能小

RIO

  • 解决short count
  • 提供方便、健壮、高效的IO
  • 两类函数
    • 无缓冲的输入输出
      • rio_readn
      • rio_writen
        • 绝不会返回不足值
    • 带缓冲的输入输出
      • rio_readlineb
        • 读文本行
        • 停止条件
          • 读了maxlen个字节
          • 遇到了EOF
          • 遇到了换行符
      • rio_readnb
        • 读字节 不区分文本和二进制文件
        • 停止条件
          • maxlen
          • 遇到EOF
      • readlineb和readnb可以混用,但不能和readn混用

总结

  • unix IO

    • 优点
      • 最基本和底部的IO形式
        • 其他的所有IO包都是用UnixIO函数补充实现的
      • 提供了访问文件元数据的方法
      • unixIO函数是异步信号安全的,可以在信号处理中使用
    • 缺点
      • 处理不足值容易出现问题
      • 读取文本行需要一些缓冲区形式,也是很容易出现问题的
      • 这些问题在标准IO和RIO中都被解决了
  • 标准IO

    • 优点
      • 利用流缓冲区减少了read和write的系统调用次数,增加了效率
      • 自动处理不足值
    • 缺点
      • 不提供访问文件元数据的方法
      • 不是异步信号安全的,不适合信号处理
      • 不适合网络套接字的输入输出
  • 读写二进制文件时绝对不可以使用的函数

    • 针对文本的IO:fgets、scanf、rio_readlineb
      • 特殊处理了EOL
    • string函数
      • 特殊处理了\0
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值