|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
写学习日记,这是学习历程的见证,同时我坚持认为是增强学习信念的法宝。以上是我学习Linux的心得体会,希望对大家的学习有所帮助,由于水平有限,本文难免有所欠缺,望请指正。
能够说统统存储体系的基本是体系挪用:open,creat,seek,read,write,mmap...的使用,要想写个高功能FS,就要深切IO体系挪用.这篇博文次要剖析了操纵文件的内核数据布局的变更及相干tips,相干I/O基本操纵,这里不讲,请参阅APUE.
在linux内核中对一切翻开的文件利用了三种数据布局来暗示:
1)每一个历程在历程表中(PCB)中都有一个纪录项
1structtask_struct{2//...3structfile*filep[NP_OPEN];4//...5};如下面内核代码filep就是一张该历程翻开的文件形貌符表,能够当作一个数组,从0入手下手计数.当我们挪用open翻开一个文件时,形貌符会++1.
1intmain(){2intfd1;3fd1=open("./test",O_RDONLY,0);4printf("%dn",fd1);5return0;6}好比这段代码,open前往的是文件创立时前往的文件形貌符,在本机无别的翻开的文件时运转程序能够看到了局为:3.这里是3是有缘故原由的,由于0,1,2这三个文件形貌符已被OS内核占用失落了,顺次为STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO.以是文件形貌符从3入手下手计数,顺次下往,那有无最年夜限定呢?再用上面代码测试下:
01intmain(){02intfd1;03inti;04for(i=0;i<1025;i++){05fd1=open("./test",O_RDONLY,0);06printf("%dn",fd1);07}08getchar();09return0;10}假如你ulimit没做任何修正的话,在到1023后就会打印-1.这是文件形貌符凌驾了体系最年夜限定,可用ulimit-n举行响应调剂.
文件形貌符在内核中会存成如许:
2)一切翻开的文件有一张大众的文件表(被一切历程共享),包括一些文件读写标记(r,w...),文件地位,援用计数(由形貌符表指向的援用数),另有一个指向i-node表的指针.内核数据布局代码以下:
1structfile{2unsignedshortf_mode;//文件操纵形式3unsignedshortf_flags;//文件翻开和把持标记4unsignedshortf_count;//翻开文件的援用计数5structm_inode*f_inode;//对应i-node6off_tf_pos;//文件地位7};3)别的关于一切翻开的文件另有一张大众的i节点表(一切历程共享),内里有一切文件的元数据信息,好比文件巨细,文件一切者.
1structstat{2intst_size;3//...4};别的这边申明下,linux只要i-node没有v-node,v-node指的是UNIX.这里我们以用的较多的linux为例.
三个数据布局能够经由过程上面这张图接洽起来:
如今让我们依据下面的常识看下读取文件text的历程,当我们挪用open函数时会发生一其中断(软),linux内核实践挪用的是sys_open.
1staticinlinelongopen(constchar*file,intflag,intmode){2externlongsys_open(constchar*,int,int);3returnsys_open(file,flag,mode);4}挪用sys_open函数,以后历程会将task_struct中的文件structfile*filep[NP_OPEN];办理指针表与内核中的file_table(一切历程共享,后面说过)举行指针毗连,全部file_table能够当作一个数组,举行指针毗连的根据是找到ref=0的项.由于假如有哪项已有文件了,ref一定会>=1的,年夜于1是由于有共享好比fork.dup2之类的操纵.
filep和file_table援用操纵如图:
然后从硬盘读取text文件,猎取inode节点.这个历程次要依据用户传进的路径(绝对/相对)找到i-node,假如text是在一个多层目次下,好比~/a/text会先读取根目次的i节点然后失掉a的目次项再读取到a的i节点再失掉a文件下的目次文件再失掉text目次项最初失掉i-node.如图所示:
最初找到text文件的i-node节点后必要注册到file_table的布局体中.
以上是全部翻开文件的历程,我们来看下新建文件的历程,新建文件和翻开文件相似,不外这里和翻开文件分歧的是新建i节点的历程.创立文件选用creat函数时实在和open一样挪用的也是sys_open函数.只不外传参纷歧样了.O_CREAT|O_TRUNC.
1intsys_creat(constchar*pathname,intmode){2returnsys_open(pathname,O_CREAT|O_TRUNC.mode);3}我们间接举行创立i-node节点的中央,当以~/a/text路径查找text的i节点时,因为a这个数据布局中还没有text这个目次项,以是查找函数会前往空.不外这里要注重我们来挪用下内核代码看下:
1intopen_namei(intdfd,constchar*pathname,intflag,2intmode,structnameidata*nd){3//...4if(!(flag&O_CREAT)){5}6}代码中有O_CREAT的判别,以是此时是不会往找这个i-node而是会往创立文件.创立文件的内容会包括权限等判别.先往a文件中增加目次项,查找余暇目次项(ref=0,后面提到过),找到了就把目次项挂载到此地位处.目次项的名字为text.最初再把文件的i-node也载进file_table中,并依据这个inode天生一张i-node表,内里有此文件的一切元数据信息.到最初sys_open(实践挪用的是do_sys_open)操纵会前往文件形貌符fd.
1longdo_sys_open(constchar*filename,intflag,intmode){2//...3returnfd;4}全部文件创立历程停止.上面我们就能够拿着这个fd对它举行统统操纵(在有权限的局限内).好比写,读.
写操纵,内核数据布局块次要是要注重以后文件指针偏移量f_pos,这个会决意你写进的地位,良多时分,操纵文件I/O函数时,翻开了一个文件举行写进后,这个时分f_pos为文件最初的指针的地位巨细,而再用这个fd举行读取的话,会发明基本读取不了数据,不懂"行情"的人大概会烦闷了,实在缘故原由就在这里,这个是后你就必要挪用lseek函数把f_pos挪动到首位.再举行读取就能够了.
最初再来讲说文件封闭操纵close.我们挪用close时,实在并没有真正封闭,而是将后面说的file_table中的ref--.由于一个文件并非你一团体在利用,这也是file_table是一切历程共享的缘故原由.ref告知os有几历程在利用,当ref变成0了,也即OS要接纳的时分.OS会把一切ref=0的对应的i节点从内核i节点数据布局中删除.不成能让这些没有人利用的一向利用体系资本.
看不懂man文档的人.在linux中,命令可分为系统基本命令和应用程序命令.系统基本命令是所有的unix类系统都支持的命令,走到哪都不变,只要是unix类系统上就肯定有. |
|