1.inode
在了解文件流指针之前,我们需要了解inode。
inode是什么?
从文件存储方向理解inode,硬盘上的最小存储单位叫做“扇区”(Sector),每个扇区能存储512字节,就是0.5KB。操作系统读取硬盘的时候,不会一个一个扇区地进行读取。这样效率非常低,所以会采用一次性读取多个扇区,把一次性读取连续多个扇区称为“块”(block)。所以由多个扇区组成的块,是文件存取的最小单位。块的大小,最常见的是4KB,即连续8个sector。
那么文件存储在块中,我们要想通过操作系统寻找到物理层面上的文件,说明,我们不仅要存储文件,更要在存储文件的时候将文件相关信息提取出来,形成一个文件信息的集合体,我们称这样的集合体为文件的元信息,所以我们需要额外的空间去保存这部分信息,这就是inode。
inode包含了什么信息?
*文件的字节数
*文件拥有者的User ID
*文件的Group ID
*文件的读、写、执行权限
*文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间
*链接数,即有多少个文件名指向这个inode
*文件数据block的位置
可以用stat命令,查看某个文件的inode信息:
stat example.txt
2.inode的大小
inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存在inode所包含的信息。
每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就已给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整个硬盘的12.8%。
查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令。
df -i
查看每个inode节点的大小,可以用如下命令:
sudo dumpe2fs -h /dev/hda | grep "Inode size"
由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未满的情况。这是,就无法在硬盘上创建新文件。
3.inode号码
每个inode都有一个号码,操作系统用inode来识别不同的文件。
Unix/Linux系统内部不是使用文件名,而是使用inode号码来识别文件。对于系统来说,文件名知识inode号码便于识别的别称或者绰号。
用户根据文件名打开文件,实际上分三步:
①系统找到这个文件名对应的inode号;
②通过inode号码获取inode信息;
③根据inode信息,找到文件数据所在的block,读出数据。
ls -i example.txt
4.文件流指针
PCB:程序控制快,当一个Linux进程启动后,会在内核空间创建一个该进程的进程控制块(PCB),PCB内部有一张文件描述符表,用来存放指向打开目标文件的对象的指针,PCB内部还有一个文件指针files,同时操作系统会给当前进程生成一个文件结构体(files_struct),其中就包括了文件描述符表(fd *array[])的索引,也包括了对想要打开的目标文件赋予什么样的权限的副操作(其他参数),也就是files_struct中同时存在着文件描述符表fd *array[]和其他附加功能,正是可以通过文件流指针的调用,我们才能对文件有更多丰富的操作。
那么文件描述符又是怎么控制文件的呢?
在上面的inode相关知识中,我们知道了 每个在硬盘中文件都有其对应的inode,那么硬盘会有专门存放这些文件inode的地方,在图中我们用inode表来表示,每个文件的inode相当于其中的一个对象,那么怎么才能进程知道哪个文件的inode结构体变量在哪呢?利用打开函数(open,fopen)和已知文件路径信息进入打开文件表,可以直接锁定目标文件的inode指针,此时两个函数都有相应的返回值来表示进程已经联系上了目标文件,并且返回值的意义也拥有该文件的相关信息的指针,open的返回值为文件描述符,该文件描述符即是在struct file_struct中的fd *array[] 的下标值,该指针数组中的元素即是指向目标文件的指针,而文件流指针就是指向了保存了该指针数组的结构体对象。
单进程能够一起启动的文件数即为文件描述符表的大小
ulimit -n