一概述:
(1)所有语言的运行时系统都提供执行I/O较高级别的工具(基于或使用Unix I/O来实现的):
*ANSI C提供标准I/O库:例如scanf和printf等带缓冲区的I/O函数。
*每个ANSI C程序开始时都有三个打开的流stdin、stdout、stderr对应于标准输入、标准输出和标准出错。
*C++用重载的<<和>>提供了类似的功能。
(2)Unix系统中,是通过由内核提供的系统级Unix I/O函数来实现这些较高级别的I/O函数的。
*Unix I/O是无缓冲的,标准I/O库是带缓冲的。
*头文件unistd.h定义了常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,代表描述符0、1、2。
(3)使用经验:
*标准I/O函数是磁盘与终端设备I/O之选。
*在网络套接字上不要使用标准I/O函数,需使用Unix I/O函数,但是由于read和write函数存在传送的字节比应用程序要求的少的情况,所以需自己实现一些比较健壮的I/O函数(暂称RIO(Robust I/O))。
二 Unix I/O:
(1)在Unix系统中,所有I/O设备,如网络、磁盘、终端都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。
(2)Unix I/O的所有输入和输出以统一且一致的方式来执行:
*打开文件:一个应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备,内核返回一个小的非负整数,叫做描述符。内核记录这个打开文件的信息,应用程序只需记住这个描述符。Unix shell创建的每个线程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)、标准出错(描述符为2)。头文件unistd.h定义了常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,可用来代替显式的描述符值。
*改变当前文件位置:内核为每个打开的文件保持一个文件位置k,初始化为0。应用程序能够通过seek操作,显式设定文件的当前位置k。
*读写文件:一个读操作从文件拷贝n>0字节到存储器,从当前位置k开始,然后将k增加到k+n。给定一个文件大小为m字节的文件,当k>=m时执行读操作会触发一个成为EOF的条件。一个写操作从存储器拷贝n>0字节到一个文件,同时更新文件位置k。
*关闭文件:当应用完成了对文件访问之后,就通知内核关闭这个文件。作为响应,内核释放这个文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。无论一个进程以何种原因终止,内核都会关闭所有打开的文件并释放它们的存储器资源。