⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 049_fs_namei_c.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 5 页
字号:
  <html lang="zh-CN" xmlns:gdoc="">  <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table {  font-size: 1em;  line-height: inherit;}div, address, ol, ul, li, option, select {   margin-top: 0px;  margin-bottom: 0px;}p {  margin: 0px;}body {        margin: 0px;          padding: 0px;    font-family: Verdana, sans-serif;  font-size: 10pt;  background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer {  position: relative;  margin-top: 1em;  margin-bottom: 1em;}/* end default css */  /* default print css */    @media print {    body {       padding: 0;       margin: 0;     }    div.google_header, div.google_footer {      display: block;      min-height: 0;      border: none;    }    div.google_header {      flow: static(header);    }    /* used to insert page numbers */    div.google_header::before, div.google_footer::before {      position: absolute;      top: 0;    }    div.google_footer {      flow: static(footer);    }    /* always consider this element at the start of the doc */    div#google_footer {      flow: static(footer, start);    }    span.google_pagenumber {      content: counter(page);    }    span.google_pagecount {      content: counter(pages);    }  }  @page {    @top {      content: flow(header);    }    @bottom {      content: flow(footer);    }  }  /* end default print css */ /* custom css *//* end custom css */  /* ui edited css */    body {    font-family: Arial;        font-size: 10.0pt;    line-height: normal;    background-color: #ffffff;  }    .documentBG {    background-color: #ffffff;  }  /* end ui edited css */</style>   </head>  <body  revision="dcbsxfpf_72kqwmrhj:358">      <div align=center id=vwb2>
  <table align=center border=0 cellpadding=0 cellspacing=0 height=5716 id=rdfz width=800>
    <tbody id=qc9l>
    <tr id=gb0d>
      <td height=5716 id=xuow valign=top width=100%>
        <pre id=sl2q>2008-1-30</pre>
        <pre id=nr:i><br id=q.qt>  <br id=cm_y>   此文件是个巨无霸,对外接口已经很清晰的列了出来.我们标注了三个极为核心的函数.集中精力分析下. &lt;&lt;情景分析&gt;&gt;也是大力解析这几个<br id=d0dr>函数.其余函数随着分析之深入,逐步介绍,如果发现疑问,再就地解决.<br id=b:ex><span id=kz1r style="FONT-FAMILY:Courier New">/*</span><br id=gruw style="FONT-FAMILY:Courier New"><span id=wif0 style="FONT-FAMILY:Courier New"> *Interface:</span><br id=yj6g style="FONT-FAMILY:Courier New"><span id=zuem style="FONT-FAMILY:Courier New"> *   int __user_walk(const char *name, unsigned flags, struct nameidata *nd)</span><br id=tx2_ style="FONT-FAMILY:Courier New"><span id=rhik style="FONT-FAMILY:Courier New"> *   int </span><font color=#3333ff id=k0k4 style="FONT-FAMILY:Courier New"><b id=cmm1>open_namei</b></font><span id=szm9 style="FONT-FAMILY:Courier New">(const char * pathname, int flag, int mode, struct nameidata *nd)</span><br id=eon1 style="FONT-FAMILY:Courier New"><span id=ufnv style="FONT-FAMILY:Courier New"> *   int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)</span><br id=wlt5 style="FONT-FAMILY:Courier New"><span id=rfc3 style="FONT-FAMILY:Courier New"> *   int vfs_readlink(struct dentry *dentry, char *buffer, int buflen, const char *link)</span><br id=dn08 style="FONT-FAMILY:Courier New"><span id=lbkg style="FONT-FAMILY:Courier New"> *   int </span><font color=#3333ff id=v3h1 style="FONT-FAMILY:Courier New"><b id=xuox>path_walk</b></font><span id=yppf style="FONT-FAMILY:Courier New">(const char * name, struct nameidata *nd);</span><br id=r36s style="FONT-FAMILY:Courier New"><span id=d.yj style="FONT-FAMILY:Courier New"> *   char * getname(const char * filename);</span><br id=fupu style="FONT-FAMILY:Courier New"><span id=ffud style="FONT-FAMILY:Courier New"> *   int permission(struct inode * inode,int mask)</span><br id=si:p style="FONT-FAMILY:Courier New"><span id=r:je style="FONT-FAMILY:Courier New"> *   int get_write_access(struct inode * inode);</span><br id=c-:o style="FONT-FAMILY:Courier New"><span id=f_ze style="FONT-FAMILY:Courier New"> *   int deny_write_access(struct file * file)</span><br id=tpzr style="FONT-FAMILY:Courier New"><span id=r03o style="FONT-FAMILY:Courier New"> *   void path_release(struct nameidata *nd)</span><br id=iqbr style="FONT-FAMILY:Courier New"><span id=xoo6 style="FONT-FAMILY:Courier New"> *   int follow_down(struct vfsmount **mnt, struct dentry **dentry)</span><br id=feq. style="FONT-FAMILY:Courier New"><span id=b5ef style="FONT-FAMILY:Courier New"> *   void set_fs_altroot(void)</span><br id=kxxz style="FONT-FAMILY:Courier New"><span id=zlmx style="FONT-FAMILY:Courier New"> *   int </span><font color=#3333ff id=y_:8 style="FONT-FAMILY:Courier New"><b id=ab-:>path_init</b></font><span id=vpm9 style="FONT-FAMILY:Courier New">(const char *name, unsigned int flags, struct nameidata *nd)</span><br id=ohxf style="FONT-FAMILY:Courier New"><span id=lwkx style="FONT-FAMILY:Courier New"> *   int vfs_follow_link(struct nameidata *nd, const char *link)</span><br id=dq0z style="FONT-FAMILY:Courier New"><span id=h08g style="FONT-FAMILY:Courier New"> *Sub Interface:</span><br id=m5g5 style="FONT-FAMILY:Courier New"><span id=d_q1 style="FONT-FAMILY:Courier New"> *   struct dentry * lookup_hash(struct qstr *name, struct dentry * base)</span><br id=fv1c style="FONT-FAMILY:Courier New"><span id=b0hf style="FONT-FAMILY:Courier New"> *</span><br id=pfdd style="FONT-FAMILY:Courier New"><span id=k0_x style="FONT-FAMILY:Courier New"> *</span><br id=flrw style="FONT-FAMILY:Courier New"><span id=cl1m style="FONT-FAMILY:Courier New"> */</span><br id=e2.t>进行之前,先旁路些mini的函数,以免干扰主要思路:<br id=z1gx>&nbsp;<br id=qxwp>char * <font color=#38761d id=u.1j><b id=by:s>getname</b></font>(const char * filename) /*分配一个页面,将用户传递的参数复制到分配的页面中,并返回此页面指针*/<br id=c3qj>       <font color=#38761d id=mvng><b id=iakh>putname</b></font>(name);  /* 和上面函数配对,释放此页面*/<br id=ddt2>这对函数涉及到一个普遍常见的操作<br id=q_sz><font color=#38761d id=if4r><b id=cy..>set_fs</b></font>(get_ds());<br id=gbq1><font color=#38761d id=l-_w><b id=dfsy>set_fs</b></font>(old_ds) <br id=sj4e>常见于内核中操作文件的操作,这对操作的含义在下面这个函数中:<br id=y37m>static inline int<b id=x.4-> do_getname</b>(const char *filename, char *page)<br id=xjd4>{<br id=ocme>	int retval;<br id=lwem>	unsigned long len = PATH_MAX + 1;<br id=tav-><br id=z2rf>	if ((unsigned long) <b id=xbg0>filename </b>&gt;= <font color=#cc0000 id=ryp4>TASK_SIZE</font>) { <font color=#3d85c6 id=ylcx>/*如果是内核传递的参数*/</font><br id=ymuj>		if (!segment_eq(<font color=#cc0000 id=fr_0><font color=#0b5394 id=rflh><b id=nt_w>get_fs</b></font>()</font>, <font color=#cc0000 id=f7st>KERNEL_DS</font>)) <font color=#0b5394 id=rslx>/*则必须addr limit 等于KERNEL_DS: 不是cpu的寄存器...*/</font><br id=z_-d>			return -EFAULT;<br id=mo6m>	} else if (TASK_SIZE - (unsigned long) filename &lt; PAGE_SIZE) <font color=#0000ff id=mlvr>/*内核传递的参数跳过这个检查*/</font><br id=ab-o>		len = TASK_SIZE - (unsigned long) filename;<br id=k57q>        .........<br id=dlgu>}<br id=vcch><br id=tndk><br id=qb7q>分析permission之前看看inode的几个相关变量:<br id=ybyb>struct inode {<br id=b9uu>	struct list_head	i_hash;<br id=ou7r>	struct list_head	i_list;<br id=xccb>	struct list_head	i_dentry;<br id=dnl1>	<br id=gf.a>	struct list_head	i_dirty_buffers;<br id=u8-u><br id=b45h>	unsigned long		i_ino;<br id=ew4g>	atomic_t		i_count;<br id=lxls>	kdev_t			i_dev;<br id=rslm>	umode_t			<font color=#38761d id=ky00><b id=p02m>i_mode</b></font>; /*LNK,REG,DIR,CHR,BLK,FIFO,SOCK |permition user|limit group|limit other*/<br id=i_n1>	nlink_t			i_nlink;<br id=a47b>	uid_t			<font color=#38761d id=i0b2><b id=xq8t>i_uid</b></font>; /*owner*/<br id=bdub>	gid_t			<font color=#38761d id=ius1><b id=woi9>i_gid</b></font>; /*owner's group?*/<br id=kob0>	kdev_t			i_rdev;<br id=mjm4>	loff_t			i_size;<br id=kyy2>	time_t			i_atime;<br id=t32t>	time_t			i_mtime;<br id=iej1>	time_t			i_ctime;<br id=hv5g>	unsigned long		i_blksize;<br id=pnvk>	unsigned long		i_blocks;<br id=n:vf>	unsigned long		i_version;<br id=jjks>	struct semaphore	i_sem;<br id=lvbm>	struct semaphore	i_zombie;<br id=dv4i>	struct inode_operations	*i_op;<br id=qc56>	struct file_operations	*i_fop;	/* former -&gt;i_op-&gt;default_file_ops */<br id=pdiw>	struct super_block	*i_sb;<br id=vovc>	wait_queue_head_t	i_wait;<br id=l9rx>	struct file_lock	*i_flock;<br id=qfur>	struct address_space	*i_mapping;<br id=npq2>	struct address_space	i_data;	<br id=uhpl>	struct dquot		*i_dquot[MAXQUOTAS];<br id=i7n_>	struct pipe_inode_info	*i_pipe;<br id=s50o>	struct block_device	*i_bdev;<br id=uh7e><br id=k::0>	unsigned long		i_dnotify_mask; /* Directory notify events */<br id=u4kp>	struct dnotify_struct	*i_dnotify; /* for directory notifications */<br id=nu6d><br id=upzh>	unsigned long		i_state;<br id=n0r6><br id=y13i>	unsigned int		i_flags;<br id=tlxs>	unsigned char		i_sock;<br id=f:_i><br id=zo__>	atomic_t		i_writecount;<br id=vfr->	unsigned int		i_attr_flags;<br id=a-y.>	__u32			i_generation;<br id=w5qa>	union {} u;<br id=z8dn>};</pre>
        <pre id=xj2y>注意i_mode被分成几个部分使用:文件模式/权限(U,G,O)对应于owener权限,本group权限,other权限<br id=nn_e>int <font color=#38761d id=xtwp><b id=ho.y>permission</b></font>(struct inode * inode,int mask) <font color=#0000ff id=v2hc>/*要不使用文件系统自定义的权限检查,要不使用默认的权限检查*/</font><br id=f89:><font color=#0000ff id=j_f3><font color=#cc6600 id=t01y><b id=t5b1>DAC: 自主访问控制</b></font></font><br id=t_dx>/*<br id=bais> *	permission()<br id=kr-t> * 根据文件的<br id=qb_-> * is used to check for read/write/execute permissions on a file.<br id=fg28> * We use "fsuid" for this, letting us set arbitrary permissions<br id=csaz> * for filesystem access without changing the "normal" uids which<br id=nhdg> * are used for other things..<br id=v6uh> */<br id=w0yx>int <font color=#38761d id=erw0><b id=m3wc>vfs_permission</b></font>(struct inode * inode,int mask) <font color=#0000ff id=qbu4>/*文件系统默认的权限检查...*/</font><br id=c9bs>{<br id=c_ya>	int mode = inode-&gt;i_mode;<br id=lq.l><br id=ya-:>	if ((mask &amp; S_IWOTH) &amp;&amp; <font color=#cc0000 id=j_a.>IS_RDONLY</font>(inode) &amp;&amp; /*<font color=#cc0000 id=waio>IS_RDONLY判断</font>文件系统的安装属性*/<br id=ehgx>		 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))<br id=d0tt>		return -EROFS; /* Nobody gets write access to a read-only fs */ <font color=#0000ff id=n67:>/*文件系统级别判断*/</font><br id=gtmc><br id=na2e>	if ((mask &amp; S_IWOTH) &amp;&amp; IS_IMMUTABLE(inode))<br id=xxc2>		return -EACCES; /* Nobody gets write access to an immutable file */ <font color=#0000ff id=t7jt>/*不可变更属性检查*/</font><br id=kjag><br id=x8kg>        <font color=#0000ff id=n0wp>/*根据当前进程是owner/group/other来解析出文件对应的limitation*/</font><br id=cg25>	if (current-&gt;fsuid == inode-&gt;i_uid) /*owner*/<br id=sqca>		mode &gt;&gt;= 6;<br id=g6yr>	else if (in_group_p(inode-&gt;i_gid)) /*group*/<br id=pv9i>		mode &gt;&gt;= 3;<br id=r-hd>        /*other*/<br id=ae8j><br id=gt8n>        /*权限容许,或者当前进程拥有DACOVERRIDE权限: DAC,<font id=f0cg size=2><a class=l href=http://uw713doc.sco.com/en/SEC_file/_Discretionary_Access_Control_DAC_ACLs.html id=kptg target=_blank>Discretionary <font color=#cc0033 id=ockv>access</font> control (<font color=#cc0033 id=pg0c>DAC</font>)</a></font>*/<br id=bx90>	if (((mode &amp; mask &amp; S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) /*CAP是posix的定义的一系列访问权限*/<br id=wfl4>		return 0;<br id=tlur><br id=alxc>	<font color=#0000ff id=r.ig>/* read and search access */</font><br id=osvz>	if ((mask == S_IROTH) ||<br id=pww.>	    (S_ISDIR(inode-&gt;i_mode)  &amp;&amp; !(mask &amp; ~(S_IROTH | S_IXOTH))))<br id=x9zw>		if (capable(CAP_DAC_READ_SEARCH))<br id=hi3g>			return 0;<br id=cq:h><br id=dmdb>	return -EACCES;<br id=ctb6>}<br id=cgyo>上面的分析随不够极度细致,也足以作为入门了,所以就看这么多吧.<br id=epo0><br id=dgzy>下面是write acess的两个函数: 此权限用于互斥mmap的VM_DENYWRITE属性和write操作. 就是mmap时指定了denywrite则普通文件就不能<br id=r_va>容许写操作了:<br id=iw8_>int <font color=#38761d id=s8gw><b id=gy:t>get_write_access</b></font>(struct inode * inode) /*普通文件写操作时判断有没有VM_DENYWRITE属性的mmap*/<br id=k1of><br id=ds5b>int <font color=#38761d id=wp6.><b id=ed50>deny_write_access</b></font>(struct file * file) /*mmap一个VM_DENYWRITE属性的区域需要拒绝普通文件的写操作*/<br id=ly3d></pre>
        <div align=center id=fu3o>
          <pre id=u77r><br id=i3y.><font id=yril size=4><font color=#0000ff id=d6g-><b id=e99e>path walk </b></font><br id=qw.t></font></pre>
        </div>
        <p align=justify id=di6r>
          <br id=wfvj>
          下面看看比较关键的一个文件系统的函数,也是文件系统之所以这么power的一个接口:字符串,路径接口.
          path_walk.先研究下路径查找过程的中间结果:<br id=gxpf>
          <font face="Courier New" id=kthy>struct nameidata {<br id=d53m>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct dentry *dentry;
          /*当前的dentry,从此目录开始查找*/<br id=ijb4>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct vfsmount *mnt;&nbsp; /*当前dentry
          所属的mnt*/<br id=ve76>
          &nbsp;&nbsp;&nbsp;&nbsp; struct qstr last;&nbsp;
          /*<font color=#0000ff id=w_.x>只有指定</font><font color=#0000ff id=nrpz>lOOKUP_PARENT时才需要关心(</font>__vfs_follow_link,使得非parent查找也有值,非主流...)*/<br id=ubfg>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned int flags; /*查找参数:no
          alt/positive/parent/follow/directory/<font color=#ff0000 id=v:sz>continue</font>*/<br id=q7es>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int last_type; /*NORM, ROOT, DOT,DOTDOT,
          <font color=#ff0000 id=of8g>BIND</font>:
          <font color=#0000ff id=u1h:>只有指定lOOKUP_PARENT时才有效</font>*/<br id=a7lv>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -