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

📄 019_using_uml.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 2 页
字号:
    }    /* 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: Verdana;        font-size: 10.0pt;    line-height: normal;    background-color: #ffffff;  }    .documentBG {    background-color: #ffffff;  }  /* end ui edited css */</style>   </head>  <body  revision="dcbsxfpf_60cr7cm55r:8">      <div id=zf3z>
  <table align=center border=0 cellpadding=0 cellspacing=0 height=5716 id=t2aa width=800>
    <tbody id=jj_y>
    <tr id=v4g1>
      <td height=5716 id=g16n valign=top width=100%>
        <pre id=tlt6>2006-8-2<br id=mjmu><br id=k7yq>  真是没有用过linux,很多事情搞不清楚呢还。读mm/shmem.c 的时候看到mmap<br id=zsau>的私有共享影射使用了tmpfs的文件,但是ls /dev/shm并没有看到那个dev/zero名<br id=ws82>字的文件。于是想搞清楚。(mm/shmem.c shmem_zero_setup)<br id=f7c->  <br id=xoav>  先是考虑ls使用什么系统调用读取文件夹内的文件名列表,开始没有经验,就是搜索<br id=jx8r>到了sysv_readdir这个系统调用.顺着看下去,觉得vfs_readdir是个关键的函数。并<br id=wsz_>通过查看tmpfs的相关代码确认了这一点。sys_open-&gt;dentry_open-&gt;<br id=rkxj>fops_get(inode-&gt;i_fop)然后看tmpfs的inode,shmem_get_inode 使用的是<br id=d0ut>simple_dir_operations。<br id=rb2c> <br id=n_vn>  然后看dcache_readdir,开始没有仔细看,只是注意到有如下的一句:<br id=ip4.>  (本文实际上都是采用kernel2.6.14)<br id=ihvq>  if (d_unhashed(next) || !next-&gt;d_inode)<br id=a3a_>					continue;<br id=x4bg>	直接注释掉,编译内核,测试。不幸,什么都没有。<br id=r1ve>	<br id=u1mj>	如此反复了好几次,后来又改shemem_setup_zero,初看觉得inode-&gt;i_link被置位0了,<br id=q1qk>去掉(注意,这里已经走入歧途了),还是没有结果。这样改来改去没有任何结果编译<br id=xcm0>了多次内核。倒是体会到,这样的小改动只需要<br id=djzb>  make<br id=n-cu>  即可,无须make clean等操作。<br id=nc1u>  <br id=v9.f>  过了几天,感觉需要先找个什么方法看看是不是这样行的通。于是直接将shmem_<br id=o:2b>zero_setup的shmem_file_setup换成相应的filp_open(注意需要创建,并且名字不<br id=n.mp>能相同)。居然可以了。(后来意识到这样不过是饮鸩止渴)<br id=b253>  于是认定只要走一个完整的filp_open就可以将问题找出来(没想到这样是在错误<br id=rkjh>的方向上越走越远)。于是将filp_open拆分,改动到shmem.c.经历了‘成功’后,这<br id=ff4a>次痛苦的时间更长了。下面是相关的改动(注意这不能工作,老是死机):<br id=cizf>int shmem_do_open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)<br id=yf5z>{<br id=u0la><br id=w-_9>	struct dentry *dentry;<br id=v0gm>	struct dentry *dir;<br id=xh83>	struct qstr *this;<br id=wttn><br id=uhvo>/*prepare ND */<br id=fpr8>	/* Fill in the open() intent data */<br id=drn0>	nd-&gt;intent.open.flags = flag;<br id=adkr>	nd-&gt;intent.open.create_mode = mode;<br id=pbzb><br id=qg.u>	/*<br id=ryh9>	 * Create - we need to know the parent. <br id=l-qz>	 */<br id=ju97>	/*Get parent nd*/<br id=nuc0>#if 0<br id=ffm:>	error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);<br id=r-t1>	if (error)<br id=bj68>		return error;<br id=ow_o>#endif	<br id=xr38>        nd-&gt;dentry = shm_mnt-&gt;mnt_root;<br id=f7t6>	 nd-&gt;mnt   = mntget(shm_mnt);<br id=l.20>	 nd-&gt;last_type= LAST_NORM;<br id=m-7x>{ /*prepare last compnet hash*/<br id=b9_c>         this= &amp;nd-&gt;last;<br id=cwoh>         unsigned long hash;<br id=aurj>	  unsigned char c;<br id=dp73>	 <br id=i6nm>	 this-&gt;name = pathname;<br id=df.s> 	 c = *(const unsigned char *)pathname;<br id=vcic><br id=gxwe>	 hash = init_name_hash();<br id=w5.9>	 do {<br id=huis>			pathname++;<br id=ttdj>			hash = partial_name_hash(c, hash);<br id=u16a>			c = *(const unsigned char *)pathname;<br id=aj4v>	} while (c &amp;&amp; (c != '/'));<br id=ujsh>	 this-&gt;len = pathname - (const char *) this-&gt;name;<br id=ui3y>	 this-&gt;hash = end_name_hash(hash);<br id=bgn6>}<br id=lii2>	<br id=x7qm>	dir = shm_mnt-&gt;mnt_root;<br id=xd:d>	nd-&gt;flags &amp;= ~LOOKUP_PARENT;<br id=qrqe>	<br id=zmpq>{	<br id=v8j5>	/*dentry = shmem__lookup_hash(&amp;nd-&gt;last, nd-&gt;dentry, nd);*/<br id=j9x9>	 dentry  = d_alloc(dir, &amp;nd-&gt;last);<br id=ea7v><br id=d-ln>	 if (!dentry)<br id=koxi>		return 0;<br id=anp->}<br id=mrjh> 	 /* dentry = inode-&gt;i_op-&gt;lookup(inode, new, nd); */<br id=lbzh>	 d_add(dentry, NULL);<br id=lr93><br id=z258>	<br id=pxhh>	/* Negative dentry, just create the file */<br id=ihfq>	/*error = shmem_create(dir-&gt;d_inode, dentry, mode, nd);*/<br id=x10z>	struct inode *inode = shmem_get_inode(dir-&gt;d_sb, S_IFREG | S_IRWXUGO, 0);;<br id=uu8d><br id=l06:>        if (inode) {<br id=juwe>		   dir-&gt;d_inode-&gt;i_size += BOGO_DIRENT_SIZE;<br id=jqzo>		   dir-&gt;d_inode-&gt;i_ctime = dir-&gt;d_inode-&gt;i_mtime = CURRENT_TIME;<br id=cvkf>		   d_instantiate(dentry, inode);<br id=j55b><br id=nw-y>		  <br id=ef-2>         }else <br id=m6b3>            return -ENOSPC;<br id=jdpb>		<br id=e22c>	 nd-&gt;dentry = dentry;<br id=r3ci>		<br id=pvvg><br id=pf:1>	return 0;<br id=nqyw>}<br id=cbeq><br id=ypi->struct file *shmem_filp_open(const char * filename, int flags, int mode)<br id=z7ra>{<br id=u4:g>	int error;<br id=l:k7>	struct nameidata nd;<br id=rlxf><br id=ji4y>	error = shmem_do_open_namei(filename, flags, mode, &amp;nd);<br id=lw__><br id=igw2><br id=pq_k>       {<br id=wq5k>       /*<br id=z9:y>       	if (!error)<br id=l..y>       		return dentry_open(nd.dentry, nd.mnt, flags);*/<br id=s6zy>       	struct file * f;<br id=gtf4>       	struct inode *inode;<br id=uwv1>       	int error;<br id=gt9w>       <br id=dxee>       	error = -ENFILE;<br id=y06f>       	f = get_empty_filp();<br id=oibz>       	if (!f)<br id=r3wu>       		goto cleanup_dentry;<br id=gyp:>       	f-&gt;f_flags = flags;<br id=ve5:>       	f-&gt;f_mode = FMODE_WRITE | FMODE_READ;;<br id=uw85>       	inode = nd.dentry-&gt;d_inode;<br id=yb2t>       <br id=yg2w>       <br id=psx6>       	file_ra_state_init(&amp;f-&gt;f_ra, inode-&gt;i_mapping);<br id=hz57>       	f-&gt;f_dentry = nd.dentry;<br id=yuwm>       	f-&gt;f_vfsmnt =nd.mnt;<br id=o36s>       	f-&gt;f_pos = 0;<br id=gevp>       	f-&gt;f_op = &amp;shmem_file_operations;<br id=dtpm>       	file_move(f, &amp;inode-&gt;i_sb-&gt;s_files);<br id=y0wu>       <br id=vmuj>       <br id=x85r>       	return f;<br id=t1.d>       <br id=wi6k>       cleanup_dentry:<br id=k_5l>       	dput(nd.dentry);<br id=prk6>       	mntput(nd.mnt);<br id=nj2l>       	return ERR_PTR(error);<br id=tpf1>       }<br id=kv4:>}<br id=shof>/*<br id=loca> * shmem_zero_setup - setup a shared anonymous mapping<br id=vc7f> *<br id=cre1> * @vma: the vma to be mmapped is prepared by do_mmap_pgoff<br id=u8la> */<br id=tp_v>void itoax(char *str, int num)<br id=tf3i>{<br id=k14z>  int i=32;<br id=lt-n>  while(i)<br id=s5wf>  {<br id=l8.n>    if(num&amp;0x1) *str++ = '1';<br id=hr.:>    else *str++='0';<br id=qfrl>    num&gt;&gt;=1;<br id=f70.>    i--;<br id=irq6>    if(num==0) break;<br id=sho3>  }<br id=ykpu>  <br id=muo:>  *str=0;<br id=ygsf>}<br id=e3vd>int shmem_zero_setup(struct vm_area_struct *vma)<br id=wglh>{<br id=sbuy>	struct file *file;<br id=ebwf>	loff_t size = vma-&gt;vm_end - vma-&gt;vm_start;<br id=wa-1><br id=ur_j>	/*file = shmem_file_setup("zero", size, vma-&gt;vm_flags);*/<br id=mbie>{  static int i=0;<br id=la7f>        char name[128], num[33];<br id=un:_>        strcpy(name,"zerov");<br id=i25b>        itoax(num,i);<br id=t68t>        strcat(name,num);<br id=czbb>        /*file  = shmem_filp_open(name,FMODE_READ|FMODE_WRITE,0700);*/<br id=mufi>	  filp_open(name,O_WRONLY|O_CREAT,0700);<br id=i1ch>	  file = shmem_file_setup(name, size, vma-&gt;vm_flags);<br id=tlyc>        file-&gt;f_dentry-&gt;d_inode-&gt;i_size=size;<br id=rewd>        i++;<br id=qag8><br id=n7y3>}<br id=xetm>	if (IS_ERR(file))<br id=ftmr>		return PTR_ERR(file);<br id=t0d6><br id=qeo_>	if (vma-&gt;vm_file)<br id=puu.>		fput(vma-&gt;vm_file);<br id=dnu8><br id=bezt>	vma-&gt;vm_file = file;<br id=b2xw>	vma-&gt;vm_ops = &amp;shmem_vm_ops;<br id=xg:l>	return 0;<br id=fduh>}<br id=hdxq>				<br id=gvp7>	痛苦的久了就想到了‘万能’的调试,实在是增很printk(何况还不知道如何查<br id=na57>看输出信息,ft)。只是知道printk,kgdb,qmenu(?)可以工作,但是我感觉<br id=plcs>User mode linux对付这个问题才是王道。<br id=uc08>  于是查找uml的使用指南,并逐步实施。<br id=b2t9>  <br id=qm1j>  <br id=sv6v>  I) 首先是找一个合适的内核版本来编译ARCH=um的内核。我选择了2.6.14,后<br id=al87>来证明这个内核比较稳定,编译没有问题。<br id=k10u>      解压缩到/usr/src/linux2.6.14-uml。<br id=tf0n>  <br id=hdv4>  II)到上述目录<br id=yl6_>      make clean<br id=beav>      make mrproper (这两个操作对于以前编译过其他arch的情况比较重要)<br id=yyo_>      make xconfig ARCH=um<br id=xb8d>      make all ARCH=um<br id=ubvu>      <br id=i2.s>      现在目录下有个linux的可执行文件。<br id=l6il>  <br id=htuj>  III)不幸,运行uml还需要一个rootfs,就是uml的‘硬盘’啦。当然下载一个<br id=y2lp>  比较快,http://user-mode-linux.sourceforge.net/dl-sf.html<br id=pyzb>  选择了Debian-3.0r0.ext2.bz2,解压缩后改名为root_fs<br id=e-oj>  <br id=r.o0>  IV)./linux ubd0=root_fs  这样就搞定了。<br id=efna>  <br id=egu.>  <br id=uygk>  V)其实还有要注意的事情:make xconfig ARCH=um的时候注意<br id=msjp>    <br id=p_d3>    1.如果有如下提示:<br id=btrr>     VFS: Cannot open root device "ubd0" or unknown-block(0,0) <br id=jn05>     则大概问题如下<br id=xkm6>     1)需要支持rootfs的文件类型,选上ext2,ext3支持<br id=cb2_>     2)选上Block devices/Virtual block device[*](ubd支持)<br id=s0ym>     <br id=z6b0>    2.如果提示: Cannot open init console <br id=ln-s>      则你的rootfs 的/dev/console文件不存在,需要<br id=a1oa>      mount -o loop root_fs /mnt <br id=xern>      #cp -dpR /dev/tty[0-9] /mnt/dev<br id=t-ni>      #cp -dpR /dev/ram* /mnt/dev<br id=n3c9>      #cp -dpR /dev/console /mnt/dev<br id=bqf0>    3.如果提示:cannot setup  thead-local storage: cannot setup LDT for <br id=vaf1>      thread-local storage, 那么证明你的rootfs使用了NPTL,不幸现在uml<br id=wh9z>      还不能很好支持这个特性。换个简单点的rootfs吧。<br id=wq6b>      <br id=me:l>  VI)具体到我推荐的这个rootfs,还是有些问题的:<br id=fitw>     1。竟然没有启动bash, 在相应的runlevel中加上启动bash的命令即可<br id=i-g5>     2。没有安装shm,编辑fstab加上相应条目即可<br id=rnlc>     3。fstab文件中 / 安装在 /dev/ubd/0,改为/dev/ubd0<br id=kpvi>     4。编译uml的时候当然要选上proc支持<br id=wcrd>     <br id=yuu9>  VII)我使用的host linux也是linux2.6.14,挺好用,如果你么有发现更好的<br id=fzta>     用这个就可以了。并且我使用的是FC4,不推荐FC5。<br id=qk2g>  <br id=ebwt>  <br id=cv1.>    这样,搞定了uml,可以测试了。我写了一个小程序,只有一行:<br id=h-lh>#include &lt;sys/mman.h&gt;<br id=x0a0>#include &lt;sys/types.h&gt;<br id=t:yj>#include &lt;fcntl.h&gt;<br id=q5do>#include &lt;unistd.h&gt;<br id=xxr9>main(int argc, char** argv)<br id=w2w:>{<br id=aqau>	int i;<br id=jt4_>	char *p_map;<br id=s.:s>	char temp;<br id=j6bk>	p_map=(char*)mmap(NULL,10*10,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);<br id=by9:>       if(p_map==NULL)<br id=p9vc>	   	printf("mmap error!\n");<br id=bb6k>}<br id=a_7l>    在host linux下编译,拷贝到uml rootfs即可。测试的时候执行  shm&amp;,让他后<br id=ojpz>台运行。<br id=x13v>   <br id=h2-r>   <br id=rtpv>    至于调试,就是:(直接在/usr/src/linux2.6.14-uml下执行)<br id=ce75>    <br id=ye8s>    #gdb<br id=f4mm>    # (gdb) set args ubd0=root_fs<br id=ej0.>    # (gdb) file linux<br id=n6qf>    # (gdb) run<br id=up4y>    # (gdb) c  (不断回车直到uml启动完成)<br id=ki9h>    # (gdb) break dcache_readdir<br id=af91>    # (gdb) c<br id=c3_->    进入到uml<br id=xy56>    #(none):shm&amp;<br id=ar2v>    #(none):ls /dev/shm<br id=zeap>    <br id=trto>    好,会在一个奇怪的地方断住, c,然后就到了dcache_readdir.<br id=oo:c>    不断的用n,s,finish等命令调试你的uml内核即可. 可以用p命令打印相应变量.<br id=b62->info break 可以看断点,clear 可以清楚断点.好像我就用了这几个命令.bt都没有<br id=ja::>用过.<br id=naw6><br id=me7y>    调试的结果很令人不快.问题依然.要注意的是内核编译有-O2优化,代码执行起<br id=fu80>来怪怪的,如果你想加一段程序,gcc看起来没有用就会不执行到(甚至都没有,优化掉<br id=koxo>了),解决的方法是:<br id=fz1o><br id=n5c0>      var=....;<br id=rww->      pirntk("",var);<br id=x78a>      <br id=cnp:>      这样可以骗过gcc,保留你的代码.<br id=e_7v>      如果你改动了几个文件,只需要<br id=m7p_>      <br id=f1-5>      make ARCH=um即可,编译很快的.<br id=no40>      <br id=kebs>     <br id=yyh8>     不再详述调试过程了,最后的转机是在2006.8.1号,昨天,突然注意到,dcache_read<br id=o8fv>dir中filp-&gt;f_dentry(/dev/shm-&gt;root of tmpfs)的地址并不是shm_mnt-&gt;root的地址,<br id=evpu>终于明白了,原来不是一棵树,赫赫.剩下的就简单了,只要修改dcache_readdir将<br id=lrtj>	struct dentry *dentry = filp-&gt;f_dentry;<br id=qip3>	换成<br id=j_65>	struct dentry *dentry = shm_mnt-&gt;root;/*注意,需要将shm_mnt声明为非static*/<br id=caqh>	然后删除:<br id=rb5m>	if (d_unhashed(next) || !next-&gt;d_inode)<br id=llkr>					continue;<br id=utt6>	就可以在ls /dev/shm的时候看到一堆  dev/zero文件了.<br id=v04_>int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)<br id=q-v.>{<br id=g19z>	struct dentry *dentry = filp-&gt;f_dentry;<br id=a2z1>	struct dentry *cursor = filp-&gt;private_data; /*dcache_dir_open 将cursor 设置为dentry ''.''*/<br id=p3b7>                                         /* cursor d_child 挂入了filp-&gt;f_dentry-&gt;d_subdirs */<br id=dfnp>	struct list_head *p, *q = &amp;cursor-&gt;d_child; <br id=o7ia>	ino_t ino;<br id=cq5i>	int i = filp-&gt;f_pos;<br id=bggp><br id=zlu1>	switch (i) {<br id=q:dz>		case 0:<br id=l1vj>			ino = dentry-&gt;d_inode-&gt;i_ino;<br id=gm::>			if (filldir(dirent, ".", 1, i, ino, DT_DIR) &lt; 0)<br id=do:o>				break;<br id=jh91>			filp-&gt;f_pos++;<br id=wnoc>			i++;<br id=o:70>			/* fallthrough */<br id=y648>		case 1:<br id=h61o>			ino = parent_ino(dentry);<br id=ouk7>			if (filldir(dirent, "..", 2, i, ino, DT_DIR) &lt; 0)<br id=wy-x>				break;<br id=pu3g>			filp-&gt;f_pos++;<br id=a_sk>			i++;<br id=frxz>			/* fallthrough */<br id=tz.y>		default:<br id=p.rz>			spin_lock(&amp;dcache_lock);<br id=tk2:>			if (filp-&gt;f_pos == 2) { /* pos=2 意味从头开始 */<br id=alp1>				list_del(q);/*将cursor从f_dentry-&gt;d_subdirs 删除*/<br id=ewme>				list_add(q, &amp;dentry-&gt;d_subdirs);/*又加回来,从而位于subdir之首*/<br id=v11m>			}<br id=lr0z><br id=rzmy>			/*从cursor 的下一个subdir 开始*/<br id=fh8l>			for (p=q-&gt;next; p != &amp;dentry-&gt;d_subdirs; p=p-&gt;next) {<br id=kd-a>				struct dentry *next;<br id=la:0>				next = list_entry(p, struct dentry, d_child);<br id=xt4e>				if (d_unhashed(next) || !next-&gt;d_inode)<br id=lxrj>					continue;<br id=jl4_><br id=rrvg>				spin_unlock(&amp;dcache_lock);<br id=f5_9>				if (filldir(dirent, next-&gt;d_name.name, next-&gt;d_name.len, filp-&gt;f_pos, <br id=nqmm>				next-&gt;d_inode-&gt;i_ino, dt_type(next-&gt;d_inode)) &lt; 0)<br id=pesu>					return 0;<br id=x3vz>				spin_lock(&amp;dcache_lock);<br id=q3xv>				/* next is still alive */<br id=uj6g>				list_del(q); /*q 是cursor, 后移一个位置 */<br id=i5t_>				list_add(q, p);<br id=bhbn>				p = q; /*从cursor 取下一个subdir*/<br id=v2ti>				filp-&gt;f_pos++;<br id=podh>			}<br id=txii>			spin_unlock(&amp;dcache_lock);<br id=w_w2>	}<br id=c1a->	return 0;<br id=lo3e>}<br id=qo_7>    <br id=wb2r>    <br id=nuh7>    最后, ls 使用的函数是:sys_getdents64.<br id=pw39>    <br id=awaq>                     2006.8.2 by hyl.<br id=hsjd>  <br id=hhb:>  <br id=u:qy>  <br id=q0m4>  <br id=brma>  <br id=jbds>      <br id=t_sa>      <br id=jlq5>  <br id=nu:a><br id=b-3a></pre>
      </td>
    </tr>
    </tbody>
  </table>
</div></body></html>

⌨️ 快捷键说明

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