系统级别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
- 表项包含stat结构的大多数信息
- 每个进程一个 描述符表
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混用
- rio_readlineb
- 无缓冲的输入输出
总结
-
unix IO
- 优点
- 最基本和底部的IO形式
- 其他的所有IO包都是用UnixIO函数补充实现的
- 提供了访问文件元数据的方法
- unixIO函数是异步信号安全的,可以在信号处理中使用
- 最基本和底部的IO形式
- 缺点
- 处理不足值容易出现问题
- 读取文本行需要一些缓冲区形式,也是很容易出现问题的
- 这些问题在标准IO和RIO中都被解决了
- 优点
-
标准IO
- 优点
- 利用流缓冲区减少了read和write的系统调用次数,增加了效率
- 自动处理不足值
- 缺点
- 不提供访问文件元数据的方法
- 不是异步信号安全的,不适合信号处理
- 不适合网络套接字的输入输出
- 优点
-
读写二进制文件时绝对不可以使用的函数
- 针对文本的IO:fgets、scanf、rio_readlineb
- 特殊处理了EOL
- string函数
- 特殊处理了\0
- 针对文本的IO:fgets、scanf、rio_readlineb