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

📄 00000049.htm

📁 一份很好的linux入门资料
💻 HTM
字号:
<HTML><HEAD>  <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人:&nbsp;weix&nbsp;(好好学习),&nbsp;信区:&nbsp;Linux&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;代码分析.txt&nbsp;<BR>发信站:&nbsp;BBS&nbsp;水木清华站&nbsp;(Thu&nbsp;Dec&nbsp;21&nbsp;18:23:23&nbsp;2000)&nbsp;<BR>&nbsp;<BR>现对Linux核心代码的文件系统(File&nbsp;System)和进程间通信模块的部分系统调用作&nbsp;<BR>分析如下。所采用核心为2.2.14的版本号。此核心工作在本子网的网关上。这次将&nbsp;<BR>分析File&nbsp;System模块下的chdir,Process&nbsp;managerment&nbsp;<BR>下的alarm这三个系统调用。所有路径均为/usr/src/linux下的相对路径。&nbsp;<BR>本次分析以源代码注释的形式给出。&nbsp;<BR>1)chdir&nbsp;<BR>File:fs/open.c&nbsp;<BR>原型:int&nbsp;sys_chdir(const&nbsp;char&nbsp;*path);&nbsp;<BR>源代码如下:&nbsp;<BR>asmlinkage&nbsp;int&nbsp;sys_chdir(const&nbsp;char&nbsp;*&nbsp;filename)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;error;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;inode&nbsp;*inode;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;dentry&nbsp;*dentry,&nbsp;*tmp;&nbsp;<BR>/*&nbsp;<BR>上面定义了两个结构指针,我就不具体分析这两个结构的内容了。原因有二,这两&nbsp;<BR>个结构十分庞大,而且&nbsp;<BR>应该是系统中很著名的结构。&nbsp;<BR>下面的这个lock_kernel(),实际上是一个macro。不过我找到在&nbsp;<BR>/usr/include/asm-sparc64/smplock.h里面&nbsp;<BR>的一段define之后,就不清楚到底在干什么了,hoho.函数末尾处的&nbsp;<BR>unlock_kernel()也是类似的一个macro。&nbsp;<BR>偶想他们的功能就是作某些系统级的锁定,防止文件系统的异常。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock_kernel();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dentry&nbsp;=&nbsp;namei(filename);&nbsp;<BR>/*&nbsp;<BR>这里dentry调用namei之后返回的。这个namei实际上调用的是__namei,在文件&nbsp;<BR>fs/namei.c里面实现的。&nbsp;<BR>这个namei函数就是根据传入的参数const&nbsp;char&nbsp;*filename,然后通过调用&nbsp;<BR>getname再转化到相应的dentry&nbsp;<BR>结构指针。最后通过dput来调整相应的inode的错误。这部分代码实在不想再看了&nbsp;<BR>。hoho.&nbsp;<BR>之后的这个PTR_ERR(STR)类型的“函数”实际上是一个macro.它其实就是强制类型&nbsp;<BR>转换((long)(str)),&nbsp;<BR>就是把namei返回的东西转化成可以标识某种具体错误的long型数据。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error&nbsp;=&nbsp;PTR_ERR(dentry);&nbsp;<BR>/*&nbsp;<BR>这里说明一下几个相关的macro是怎么定义的。&nbsp;<BR>#define&nbsp;IS_ERR(ptr)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((unsigned&nbsp;long)(ptr)&nbsp;&gt;&nbsp;(unsigned&nbsp;&nbsp;<BR>long)(-1000))&nbsp;<BR>#define&nbsp;S_ISDIR(m)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(((m)&nbsp;&amp;&nbsp;S_IFMT)&nbsp;==&nbsp;S_IFDIR)&nbsp;<BR>#define&nbsp;MAY_EXEC&nbsp;1&nbsp;<BR>#define&nbsp;ENOTDIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Not&nbsp;a&nbsp;directory&nbsp;*/&nbsp;<BR>其中:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;S_IFDIR&nbsp;&nbsp;0040000&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;S_IFMT&nbsp;&nbsp;00170000&nbsp;<BR>这样一些地方就很明了了。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(IS_ERR(dentry))&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;out;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inode&nbsp;=&nbsp;dentry-&gt;d_inode;&nbsp;<BR>/*&nbsp;<BR>如果dentry有错,就unlock_kernel然后退出。&nbsp;<BR>要不就把刚才在namei里面返回的dentry结构的d_inode元素赋给inode,这是文件&nbsp;<BR>系统的inode结点。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error&nbsp;=&nbsp;-ENOTDIR;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!S_ISDIR(inode-&gt;i_mode))&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;dput_and_out;&nbsp;<BR>/*&nbsp;<BR>现在本函数中的inode结构已经被赋值了。但是如果inode-&gt;i_mode的信息表示这个&nbsp;<BR>dentry不是一个目录,&nbsp;<BR>那么就认为是出错,通过goto转跳到dput_and_out去处理。顾名思义也知道这个转&nbsp;<BR>跳是干什么的。Linux&nbsp;<BR>Kernel&nbsp;source&nbsp;code的风格真的很好哦,hoho。接下来调用permission来检测这个&nbsp;<BR>inode所表示的目录对&nbsp;<BR>于执行该系统调用的进程的属主是否可“执行”的。如果该进程的属主没有权限“&nbsp;<BR>执行”这个目录,那么&nbsp;<BR>返回的error就不是0了。于是接下来的goto就会被执行。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error&nbsp;=&nbsp;permission(inode,MAY_EXEC);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(error)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;dput_and_out;&nbsp;<BR>/*&nbsp;<BR>如果执行到了这里,那就说明一切很顺利。&nbsp;<BR>下面的就是通过dentry类型的中间变量tmp来实现原先的和现在要change到的两个&nbsp;<BR>dentry之间的转换。这种&nbsp;<BR>c=a;a=b;b=c类型的“算法”应该是很常见的。hoho。&nbsp;<BR>那么在两个相关的dentry的信息交换完了以后,sys_chdir也应该结束了,hoho。&nbsp;<BR>&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp&nbsp;=&nbsp;current-&gt;fs-&gt;pwd;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current-&gt;fs-&gt;pwd&nbsp;=&nbsp;dentry;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dentry&nbsp;=&nbsp;tmp;&nbsp;<BR>&nbsp;<BR>dput_and_out:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dput(dentry);&nbsp;<BR>out:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlock_kernel();&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;error;&nbsp;<BR>}&nbsp;<BR>&nbsp;<BR>2)alarm&nbsp;<BR>File:kernel/sched.c&nbsp;<BR>原型:int&nbsp;sys_alarm(long&nbsp;sedonds);&nbsp;<BR>调用的源代码如下:&nbsp;<BR>asmlinkage&nbsp;unsigned&nbsp;int&nbsp;sys_alarm(unsigned&nbsp;int&nbsp;seconds)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;itimerval&nbsp;it_new,&nbsp;it_old;&nbsp;<BR>/*&nbsp;<BR>这里定义了两个itimerval结构的变量it_new,it_old。&nbsp;<BR>结构itimerval在/usr/include/time.h中定义了:&nbsp;<BR>struct&nbsp;&nbsp;itimerval&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;&nbsp;timeval&nbsp;it_interval;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;&nbsp;timeval&nbsp;it_value;&nbsp;<BR>};&nbsp;<BR>其中:&nbsp;<BR>struct&nbsp;timeval&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tv_sec;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;suseconds_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tv_usec;&nbsp;<BR>};&nbsp;<BR>在itimerval结构里面的两个元素,分别为时间间隔it_interval和当前时间&nbsp;<BR>it_value.从代码中可以看出,&nbsp;<BR>它们都是timeval结构的变量,包含了这样两个信息:秒数和毫秒数(seconds,&nbsp;<BR>microseconds)。其实这两&nbsp;<BR>个数据类型time_t和suseconds_t如果找到最初的定义,会发现他们其实都是long&nbsp;<BR>型的,不过被typedef&nbsp;<BR>了。这样的情况在Linux&nbsp;Kernel的source&nbsp;code中还有很多。&nbsp;<BR>然后下面定义了一个unsigned&nbsp;int的变量oldalarm用于返回。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;int&nbsp;oldalarm;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it_new.it_interval.tv_sec&nbsp;=&nbsp;it_new.it_interval.tv_usec&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it_new.it_value.tv_sec&nbsp;=&nbsp;seconds;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it_new.it_value.tv_usec&nbsp;=&nbsp;0;&nbsp;<BR>/*&nbsp;<BR>以上的代码是对it_new做了初始化。然后就是调用do_setitimer函数来实现时间的&nbsp;<BR>设置。这个函数的入口&nbsp;<BR>参数,我想就不用多说了,只需要说明一下第一个参数是在文件&nbsp;<BR>/usr/include/time.h中定义的宏:&nbsp;<BR>#define&nbsp;ITIMER_REAL&nbsp;0&nbsp;<BR>这里我先不跟踪到do_setitimer函数里面而继续分析sys_alarm这个函数。因为把&nbsp;<BR>it_old的地址作为参数给&nbsp;<BR>了函数do_setitimer了,所以就可以实际的改变it_old内个元素的值。调用&nbsp;<BR>do_setitimer之后就把&nbsp;<BR>it_old.it_value.tv_sec的值赋给了oldalarm了。之后就是如果it_old.&nbsp;<BR>it_value.tv_sec得到了不为零的值,oldalarm自加1。看来有必要简单的分析一下&nbsp;<BR>do_setitimer这个函数,不过最好还是不在书面做出了,因为&nbsp;<BR>涉及调用函数的层次太深了。总的来说就是通过do_setitimer在一较底层上给&nbsp;<BR>it_old做了一个“初始化”。&nbsp;<BR>总的情况是sys_alarm=&gt;do_setitimer=&gt;do_getitimer=&gt;jiffiestotv,最后在这个&nbsp;<BR>jiffiestotv里面实现了&nbsp;<BR>赋值。&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_setitimer(ITIMER_REAL,&nbsp;&amp;it_new,&nbsp;&amp;it_old);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldalarm&nbsp;=&nbsp;it_old.it_value.tv_sec;&nbsp;<BR>/*&nbsp;&nbsp;<BR>通过逐层分析do_setitimer以及里面的调用,我们可以知道这里的it_old.&nbsp;<BR>it_value.tv_sec实际上是jiffies&nbsp;<BR>除以一个常数。而这个jiffies,在kernel/sched.c里面是这么定义的:&nbsp;<BR>unsigned&nbsp;long&nbsp;volatile&nbsp;jiffies=0&nbsp;<BR>这样我们就容易理解为什么如果本函数的参数为0的时候本函数返回0了。至于为什&nbsp;<BR>么实际设置了一个时间的&nbsp;<BR>情况下返回值oldalarm要自加1,这个我想应该是在系统级上对时间设置之后做的&nbsp;<BR>变换吧。纯属猜测。&nbsp;<BR>下面这两行英文是在源代码中作者的注释。我想意思是很清楚的吧?hoho.&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ehhh..&nbsp;We&nbsp;can't&nbsp;return&nbsp;0&nbsp;if&nbsp;we&nbsp;have&nbsp;an&nbsp;alarm&nbsp;pending..&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And&nbsp;we'd&nbsp;better&nbsp;return&nbsp;too&nbsp;much&nbsp;than&nbsp;too&nbsp;little&nbsp;anyway&nbsp;<BR>*/&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(it_old.it_value.tv_usec)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldalarm++;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;oldalarm;&nbsp;<BR>/*&nbsp;<BR>这样,sys_alarm的分析就结束了。&nbsp;<BR>*/&nbsp;<BR>}&nbsp;<BR>&nbsp;<BR>--&nbsp;<BR>&nbsp;<BR>※&nbsp;来源:·BBS&nbsp;水木清华站&nbsp;smth.org·[FROM:&nbsp;202.118.74.64]&nbsp;<BR><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER></BODY></HTML>

⌨️ 快捷键说明

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