对于计算机来说,I/O代表了计算机与外界的交互,交互的对象可以是人或其他设备.而对于程序来说,I/O涵盖的范围更广.一个程序的I/O指代了程序与外界的交互,包括文件,管道,网络,命令行.I/O指代任何操作系统理解为文件的事务.许多操作系统都将各种具有输入和输出该鸟的实体—包括设备,磁盘文件,命令行等统称为文件.
C语言文件操作通过一个FILE结构的指针来进行.fopen()函数返回一个FILE结构指针.在操作系统层面上,文件操作也由一个类似于FILE的概念.在Linux里,这叫做文件描述符(file description) ,在windows里,叫做句柄(handle).用户通过某个函数打开文件获得句柄.设计句柄的原因在于句柄可以防止用户随意读写操作系统内核的文件对象,文件句柄总是和内核的文件对象相关联的.但如何关联细节用户并不可’.内核可以通过句柄来计算出内核里文件对象的地址. 在内核中,每一个进程都有一个私有的打开文件列表,这个列表事业个指针数组,每一个元素都指向一个内核的打开文件对象.而fd就是这个下标.当用户打开一个文件时,内核会在内部生成一个打开的文件对象,并在这个表里找到一个空的项,让这一项指向一个打开的文件对象,并返回这一项的下标做为fd.由于这个表处于内核,并且用户无法访问到,因此用户及时有fd ,也无法得到打开的而文件对象的地址,只能通过系统提供的函数来操作.在C语言中,通过FILE结构操作文件 ,FILE 结构必定和fd有一一对应的关系.
下图展示了FILE ,fd 打开文件列表和打开文件对象之间的关系:
图中内核指针p指向该进程的代开文件列表,所以只要有fd,就可以使用fd+p 来得到打开文件列表的某一项地址.
参考:
<<UNIX环境高级编程>>
<<程序员的自我修养>>