分享
 
 
 

File结构

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

在Linux里,每一个档案都有一个file结构和inode结构,inode结构是用来让Kernel做管理的,而file结构则是我们平常对档案读写或开启,关闭所使用的。当然,从user的观点来看是看不出什么的。在Linux里,档案的观念应用的蛮广泛的,甚至是写一个driver你也只要提供一组的file operations就可以完成了。我们现在来看看File结构的内容。

struct file {

struct file *f_next,**f_pprev;

struct dentry *f_dentry;

struct file_operations *f_op;

mode_t f_mode;

loff_t f_pos;

unsigned int f_count,f_flags;

unsigned long f_reada,f_ramax,f_raend,f_ralen,f_rawin;

struct fown_struct f_owner;

unsigned long f_version;

void *private_data;

};

比起super_block和inode结构,file结构就显得小多了,file结构也是用串行来管理,f_next会指到下一个file结构,而f_pprev则是会指到上一个file结构地址的地址,不过,这个字段的用法跟一般指到前一个file结构的用法不太一样,有机会再跟各位讨论,f_dentry会记录其inode的dentry地址,f_mode为档案存取的种类,f_pos则是目前档案的offset,每次读写都从offset记录的位置开始读写,f_count是此file结构的reference cout,f_flags则是开启此档案的模式,f_reada,f_ramax,f_raend,f_ralen,f_rawin则是控制read ahead的参数,f_owner记录了要接收SIGIO和SIGURG的行程ID或行程群组ID,private_data则是tty driver所使用的字段。最后,我们来看看f_op这个字段。这个字段记录了一组的函式是专门用来使用档案的。

? llseek(file,offset,where)

我们写程序会呼叫lseek()系统呼叫设定从档案那个位置开始读写,这个函式你可以不用提供,因为系统已经有一个写好的,但是系统提供的llseek()没有办法让你将where设为SEEK_END,因为系统不知道你的档案长度是多少,所以没办法提供这样的服务。如果你不提供llseek()的话,那系统会直接使用它已经有的llseek()。llseek()必须要将file-offset的值做改新。

? read(file,buf,buflen,poffset)

当我们读取一个档案时,最终就是会呼叫read()这个函式来读取档案内容。这些参数VFS会替我们准备好,至于poffset则是offset的指针,这是要告诉read()从那里开始读,读完之后必须更新poffset的内容。请注意,在这里buf是一个地址,而且是一个位于user space的地址。

? write(file,buf,buflen,poffset)

write()的动作就跟read()是相反的,参数也都一样,buf依然是位于user space的地址。

? readdir(file,dirent,filldir)

这是用来读取目录的下一个direntry的,其中file是file结构地址,dirent则是一个readdir_callback结构,这个结构里包含了使用者呼叫readdir()系统呼叫时所传过去的dirent结构地址,filldir则是一个函式指针,这个函式在VFS已经有提供了,这个函式其实是增加了kernel在读取dirent方面的弹性。当档案系统的readdir()被呼叫时,在它把下一个dirent取出来之后,应该要呼叫filldir(),让它把所需的资料写到user space的dirent结构里,也许还会多做些处理。有兴趣的朋友可以参考的filldir()函式。

? poll(file,poll_table)

之前的Kernel版本本来是在file_operations结构里有select()函式而不是poll()函式的。但是,这并不代表Linux不提供select()系统呼叫,相反的,Linux仍然提供select()系统呼叫,只不过select()系统呼叫implement的方式是使用poll()函式来做的。

? ioctl(inode,file,cmd,arg)

ioctl()这个函式其实有很大的用途,尤其它可以做为user space的程序对Kernel的一个沟通管道。那ioctl()是什么时候被呼叫呢? 还记得平常写程序时偶而会用到ioctl()系统呼叫来直接控制档案或device吗? 是的,ioctl()系统呼叫最后就是把命令交给档案的f_op-ioctl()来执行。f_op-ioctl()要做的事很简单,只要根据cmd的值,做出适当的行为,并传回值即可。但是,ioctl()系统呼叫其实是分几个步骤的,第一,系统有几个内定的command它自己可以处理,在这种情形下,它不会呼叫f_op-ioctl()来处理。如果user指定的command是以下的一种,那VFS会自己处理。

o FIONCLEX

清除档案的close-on-exec位。

o FIOCLEX

设定档案的close-on-exec位。

o FIONBIO

如果arg传过来的值为0的话,就将档案的O_NONBLOCK属性去掉,但是如果不等于0的话,就将O_NONBLOCK属性设起来。

o FIOASYNC

如果arg传过来的值为0的话,就将档案的O_SYNC属性去掉,但是如果不等于0的话,就将O_SYNC属性设起来。只是在Kernel 2.2.1时,这个属性的功能还没完成。

如果cmd的值不是以上数种,而且如果file所代表的不是普通的档案的话,像是device之类的特殊档案,VFS会直接呼叫f_op-ioctl()去处理。但是如果file代表普通档案的话,那VFS会呼叫file_ioctl()做另外的处理。何谓另外的处理呢? file_ioctl()会再过?一次cmd的值,如果是以下数种,它会先做些处理,然后再呼叫f_op-ioctl(),不管怎么样,file_ioctl()最后都会再呼叫f_op-ioctl()去处理。

o FIBMAP

先将arg指到的档案block number取出来,并呼叫f_op-bmap()计算出其disk上的block number,最后再将计算出来的block number放到arg参数里。

o FIGETBSZ

先取得档案系统block的大小并放入arg的参数里。

o FIONREAD

将档案剩下尚未读取的长度写到arg里。比方说档案大小是1000,而f_op-offset的值是300,表示还有700个byte尚未读取,所以,将700写到arg参数里。

? mmap(file,vmarea)

这个函式是用来将档案的部分内容映像到内存中的,file是指要被映像的档案,而vmarea则是用来描述到映像到内存的那里。

? open(inode,file)

当我们呼叫open()系统呼叫来开启档案时,open()会把所有的事都做好,最后则会呼叫f_op-open()看档案系统是否要做些什么事,一般来讲,VFS已经把事做好了,所以很多系统事实上根本不提供这个函式,当然,你要提供也可以,比方说,你可以在这个函式里计算这个档案系统的档案被使用过多少次等。

? flush(file)

这个函式也是新增加的,这个函式是在我们呼叫close()系统呼叫来关闭档案时所呼叫的。只要你呼叫close()系统呼叫,那close()就会呼叫flush(),不管那个时候f_count的值是否为0。这个函式我不是很确定在做什么的,事实上,在Ext2里也没有提供这么一个函式,也许是在关闭档案之前,VFS允许档案系统先做些backup的动作吧。

? release(inode,file)

这个函式也是在close()系统呼叫里使用的,当然,不尽在close()中使用,在别的地方也是有使用到。基本上,这个函式的定位跟open()很像,不过,当我们对一个档案呼叫close()时,只有当f_count的值归0时,VFS才会呼叫这个函式做处理。一般来讲,如果你在open()时配置了一些东西,那应该在release()时将配置的东西释放掉。至于f_count的值则是不用在open()和release()中控制,VFS已经在fget()和fput()中增减f_count了。

? fsync(file,dentry)

fsync()这个函式主要是由buffer cache所使用,它是用来跟file这个档案的资料写到disk上。事实上,Linux里有两个系统呼叫,fsync()和fdatasync(),都是呼叫f_op-fsync()。它们几乎是一模一样的,差别在于fsync()呼叫f_op-fsync()之前会使用semaphore将f_op-fsync()设成critical section,而fdatasync()则是直接呼叫f_op-fsync()而不设semaphore。

? fasync(fd,file,on)

当我们呼叫fcntl()系统呼叫,并使用F_SETFL命令来设定档案的参数时,VFS就会呼叫fasync()这个函式,而当读写档案的动作完成时,行程会收到SIGIO的讯息。

? check_media_change(dev)

这个函式只对可以使用可移动的disk的block device有效而已,像是MO,CDROM,floopy disk等等。为什么对这些可以把disk随时抽取的需要提供这么一个函式呢? 其实,从字面上我们大概可以知道,这是用来检查disk是否换过了,以CDROM为例,每一个光盘片都代表一个档案系统,如果今天我们把光盘片换掉了,那表示这个档案系统不存在了,如果user此时去读取这个档案系统的资料,那会发生什么事? 很有可能系统就这么出事了。所以,对于这种的device,每当在mount时,我们就必须检查其中的disk是否换过了,如何检查呢? 当然只有档案系统本身才知道,所以,档案系统必须提供此函式。

? revalidate(dev)

这个函式跟上面的check_media_change()有着相当的关系。当user执行mount要挂上一个档案系统时,mount会先呼叫里的check_disk_change(),如果档案系统所属的device有提供这个函式的话,那check_disk_change()会先呼叫f_op-check_media_change()来检查是否其中的disk有换过,如果有则呼叫invalidate_inodes()和invalidate_buffers()将跟原本disk有关的buffer或inode都设为无效,如果档案系统所属的device还有提供revalidate()的话,那就再呼叫revalidate()将此device的资料记录好。

? lock(file,cmd,file_lock)

这个函式也是新增加的,在Linux里,我们可对一

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有