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