关于硬盘中的静态文件与inode:例如文件存储在扇区中,一个文件占用10个字节,一个扇区为512字节,这样的情况下一个扇区就只放了一个实际为10字节的文件,余下的502字节不可存放其他文件,因为扇区已经是可以访问的最小单位了。
所以,为了能够去索引到需要的文件,就有了硬盘中的索引表,如果表被破坏,文件就找不到了。
这个表项就是inode,i节点,每个节点就是一个相关信息,每一个文件一个inode,一个inode就是一个结构体,一数字作为编号,通过遍历去寻找节点。
格式化一般分为快速格式化和底层格式化。快速格式化,只是对表项进行删除没这样就找不到内容了,但本质上内容还在,能够被找回硬件的信息,但一般只能回复已知的格式的内容。底层格式化,就不单单只删除表项,删除的东西能恢复,但成本会很高。
内存中被打开的文件与vnode(v节点):程序中打开的文件就属于这个进程,一个进程就有一个相应的数据结构(进程信息表),表中有一项指针,指向文件管理表,记录打开的文件与相关信息,表中信息打开的inode就是文件的fd,最终找到的文件管理结构体叫vnode。
文件与流:流(stream)文件是一个栈(像一个栈)字符一个个读出、写入,形成流,是动态的,抽象出来的,文件操作时形成了IO流。
文件指针:针对动态文件而言,在内存中以流的形式体现,文件流十分长,以何种心方式去体现位置,以文件指针表示在操作的位置,是文件管理表(结构体)中的一个指针。文件指针实际是vnode上的一个元素,表示了正在操作文件流的位置贸易lseek()函数进行间接访问。
打开一个新问津默认打开lseek位置在开头write/read函数本会移动lseek指针,读n位就会移动n位。
lseek也支持人为去改变文件的位置off_t lseek(int fd,off_t offset,int whence);offset为偏移量,whence为参照点(SEEK_SET文件头、SEEK_CUR当前位置、SEEK_END文件尾)。
lseek返回成功的偏移量,read/write的读写位置受lseek操作。
write写完内容时,lseek在尾部,所以这时候去read文件时,内容为空。
用lseek计算文件的长度:linux中无api/函数去计算文件的长度,因为lseek可以做到这个功能。
ret=lseek(fd,0,SEEK_SET);将指针移到文件头
ret=lseek(fd,0,SEEK_END);计算从头到尾的长度
新打开一个文件,然后去计算从头到尾的偏移量
使用lseek构建空洞文件,该文件没有字符(/t、/n都没有),用lseek去移动指针,写10个空洞字节,再写2字节的内容=12字节,空的文件是线程构建同一文件是有大用的。
同一个进程多次(同时)打开同一个文件:
buf[20]={0};
fd1=open("a.txt",RDWR);
fd2=open("a.txt",RDWR);
ret1=read(fd1,buf,20);
memset(buf,0,sizeof(buf));
ret2=ret(fd2,buf,20);
结果fd1和fd2各自读各自的,lseek不是同一个,因为一个fd管理一个数据管理表。重复(同时)打开同一个文件进行写入,实际上是在内存中各写各的,最后写入硬盘时后者覆盖前者。
接续写使用O_APPEND,核心还是lseek,移动自己的lseek时把另一个文件的lseek也给移动到相应的位置, O_APPEND对文件的操作是原子级别的,该操作不可被打断,原子操作是阻塞的,干不完活,后面的代码不会动。
本章先写到这,下一章将对文件共享方面进行介绍。