学习目标
- 理解Unix I/O的设计与应用
- 理解输入输出重定向的实现机制
Unix I/O
一个 Unix 文件就是一个 m 字节的序列。所有的 I/O 设备,如网络,磁盘和终端,都被模型化为文件。这种将设备优雅地映射为文件的方式,允许 Unix 内核引出一个简单、低级的应用接口,称为UnixI/O
。这使得所有的输入输出都用同一种方式来进行:
- 打开文件
- 一个应用程序通过内核打开文件
- 内核返回一个小的非负整数,叫做描述符
- 内核记录这个文件的所有信息,应用程序记录描述符
- 改变文件的当前位置
- 对于打开的文件,内核保持一个
文件位置k
,初始为0,字节偏移量 - 应用程序可以通过 seek 操作,显式地设置文件的当前位置为 k
- 对于打开的文件,内核保持一个
- 读写文件
- 一个读操作就是从文件拷贝 n>0 个字节到存储器,从当前文件位置k开始,然后将k增加到 k+n。
- 给定一个字节大小为 m 的文件,当 K≥m 时执行读操作会触发一个称为 end-of-file(EOF) 的条件。
- 关闭文件
- 当应用完成访问这个文件后,会通知内核关闭这个文件
- 内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中
一次一个字节地从标准输入拷贝到标准输出:
|
|
用RIO包健壮地读写
RIO(Robust I/O)提供了两类函数:
- 无缓冲的输入输出函数
- 直接在存储器和文件之间传送数据,没有应用级缓冲。它们对将二进制数读写到网络和从网络读写二进制数据尤其有用。
- 带缓冲的输入输出函数
RIO无缓冲的输入输出函数:1234ssize_t rio_readn(int fd, void *usrbuf, size_t n);ssize_t rio_writen(int fd, void *usrbuf, size_t n);
rio_readn
函数描述从描述符 fd 的当前文件位置最多传送 n 个字节到存储器位置usrbuf
。在遇到 EOF 时只能返回一个不足值。rio_writen
函数从位置usrbuf
传送 n 个字节到描述符 fd。
重定向
使用fork
:子进程实际上是会继承父进程打开的文件的。在fork之后,子进程实际上和父进程的指向是一样的,这里需要注意的是会把引用进程加1,如下图所示:
重定向的实现:只需要使用dup2(oldfd,newfd)
即可。我们只需要改变文件描述符指向的文件,也就完成了重定向过程,下图我们把指向中端的描述符指向了磁盘文件,也就把终端上的输出保存在了文件中: