第十章 系统级I/O
输入/输出(I/O)
: 是指主存
和外部设备
(如磁盘,终端,网络)之间拷贝数据过程。
高级别
I/O
函数scanf
和printf
<<
和>>
- 使用系统级
I/O
函数实现
系统级
I/O
函数。Q
:大多数时候高级别I/O
函数都运行良好,为什么我们还要学Unix I/O
A
:
- 了解
Unix I/O
将帮助你理解其他的系统概念。
- 要深入理解其他概念,必须理解
I/O
。
- 要深入理解其他概念,必须理解
- 有时你除了使用
Unix I/O
别无选择
- 标准
I/O库
没有提供读取文件元数据
的方式。
- 如
文件大小
或文件创建时间
。
- 如
- 用于
网络编程
十分冒险。
- 标准
- 了解
10.1 Unix I/O
一个
Unix 文件
就是一个m
个字节的序列:- 所有
I/O
设备都被模型化为文件
。 - 而所有的输入和输出都被当做相应文件的
读和写
。
- 所有
设备
优雅地映射成文件
,允许Unix
内核引出一个简单,低级的应用接口
。叫做Unix I/O
使得所有的输入输出都能以一种统一且一致的方式来执行。
打开文件: 应用程序要求内核打开文件
内核
返回一个小的非负整数
,叫做描述符
- 等于
内核
分配一个文件名,来标示当前的文件。 内核
记录有关这个打开文件的所有信息。应用程序只需要记住标示符。
- 等于
Unix
外壳创建进程时都有三个
打开的文件- 标准输入(标示符
0
) - 标准输出(标示符
1
) - 标准错误(标示符
2
) - 头文件
<unistd.h>
定义了常量代替显式的描述符值
STDIN_FILENO
STDOUT_FILENO
STDERR_FILENO
- 标准输入(标示符
改变当前文件的位置(非文件目录)
对于每个打开的文件,内核保持一个
文件位置k
- 初始为
0
。 文件位置
即是从文件开头起始的字节偏移量
。
- 初始为
执行
lseek
操作,显式地设置文件位置
。
读写文件。
一个
读操作
就是从文件拷贝n
个字节到存储器,然后将k
增加到k+n
。- 给定一个大小为
m
字节的文件,当k>=m
时执行读操作会触发一个称 为end-of-file(EOF)
的条件。
- 应用程序能检测到这个
条件
(或者说信号?) - 文件结尾并没有这样的符号。
- 应用程序能检测到这个
- 给定一个大小为
写操作
就是从存储器拷贝n
个字节到一个文件,从当前文件位置
k开始,然后更新k
。
关闭文件 :当应用程序完成了文件的访问,通知
内核
关闭文件。响应
内核
释放文件打开时创建的数据结构。- 将
描述符
恢复到可用的描述符池中。
无论一个进程因为何种原因被关闭,内核会关闭所有它打开的文件。
10.2 打开和关闭文件
进程
是通过调用 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