?? 9.html
字號(hào):
$./test<br>Please input a number<p>36<br>Total from 0 to 36 is 666<p> 可見,修改成功;<p> 而且,對(duì)相關(guān)源碼的進(jìn)一步分析可知,在此版本的內(nèi)核中,從/usr/src/linux/arch/i386/kernel/entry.S<p> 文件中對(duì) sys_call_table 表的設(shè)置可以看出,有好幾個(gè)系統(tǒng)調(diào)用的服務(wù)例程都是定義在/usr/src/linux/kernel/sys.c 中的同一個(gè)函數(shù):<p>asmlinkage int sys_ni_syscall(void)<br>{<br>return -ENOSYS;<br>}<p> 例如第188項(xiàng)和第189項(xiàng)就是如此:<p>... ...<p>.long SYMBOL_NAME(sys_sendfile)<br>.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */<br>.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */<br>.long SYMBOL_NAME(sys_vfork) /* 190 */<p>... ...<p> 而這兩項(xiàng)在文件 /usr/src/linux/include/asm-386/unistd.h 中卻申明如下:<p>... ...<br>#define __NR_sendfile 187<br>#define __NR_getpmsg 188 /* some people actually want streams */<br>#define __NR_putpmsg 189 /* some people actually want streams */<br>#define __NR_vfork 190<p> 由此可見,在此版本的內(nèi)核源代碼中,由于asmlinkage int sys_ni_syscall(void) 函數(shù)并不進(jìn)行任何操作,所以包括 getpmsg, putpmsg 在內(nèi)的好幾個(gè)系統(tǒng)調(diào)用都是不進(jìn)行任何操作的,即有待擴(kuò)充的空調(diào)用; 但它們卻仍然占用著sys_call_table表項(xiàng),估計(jì)這是設(shè)計(jì)者們?yōu)榱朔奖銛U(kuò)充系統(tǒng)調(diào)用而安排的; 所以只需增加相應(yīng)服務(wù)例程(如增加服務(wù)例程getmsg或putpmsg),就可以達(dá)到增加系統(tǒng)調(diào)用的作用。<center><A HREF="#Content">[目錄]</A></center><hr><br><A NAME="I481" ID="I481"></A><center><b><font size=+2>一個(gè)簡單程序的分析----深至內(nèi)核</font></b></center><br> A small trail through the Linux kernel<p>Andries Brouwer, aeb@cwi.nl 2001-01-01<p>A program<br>---------------------------------------------------------------------------------------------------<br>#include <unistd.h><br>#include <fcntl.h><br>int main(){<br> int fd;<br> char buf[512];<p> fd = open("/dev/hda", O_RDONLY);<br> if (fd >= 0)<br> read(fd, buf, sizeof(buf));<br> return 0;<br>}<br>---------------------------------------------------------------------------------------------------<p>This little program opens the block special device referring to the first IDE disk, and if the open succeeded reads the first sector. What happens in the kernel? Let us read 2.4.0 source.<br><center><A HREF="#Content">[目錄]</A></center><hr><br><A NAME="I482" ID="I482"></A><center><b><font size=+2>open</font></b></center><br>The open system call is found in fs/open.c:<p>---------------------------------------------------------------------------------------------------<br>int sys_open(const char *filename, int flags, int mode) {<br> char *tmp = getname(filename);<br> int fd = get_unused_fd();<br> struct file *f = filp_open(tmp, flags, mode);<br> fd_install(fd, f);<br> putname(tmp);<br> return fd;<br>}<br>---------------------------------------------------------------------------------------------------<p>The routine getname() is found in fs/namei.c. It copies the file name from user space to kernel space:<p>---------------------------------------------------------------------------------------------------<br>#define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL)<br>#define putname(name) kmem_cache_free(names_cachep, (void *)(name))<p>char *getname(const char *filename) {<br> char *tmp = __getname(); /* allocate some memory */<br> strncpy_from_user(tmp, filename, PATH_MAX + 1);<br> return tmp;<br>}<br>---------------------------------------------------------------------------------------------------<p>The routine get_unused_fd() is found in fs/open.c again. It returns the first unused filedescriptor:<p>---------------------------------------------------------------------------------------------------<br>int get_unused_fd(void) {<br> struct files_struct *files = current->files;<br> int fd = find_next_zero_bit(files->open_fds,<br> files->max_fdset, files->next_fd);<br> FD_SET(fd, files->open_fds); /* in use now */<br> files->next_fd = fd + 1;<br> return fd;<br>}<br>---------------------------------------------------------------------------------------------------<p>Here current is the pointer to the user task struct for the currently executing task.<p>The routine fd_install() is found in include/linux/file.h. It just stores the information returned by filp_open()<p>---------------------------------------------------------------------------------------------------<br>void fd_install(unsigned int fd, struct file *file) {<br> struct files_struct *files = current->files;<br> files->fd[fd] = file;<br>}<br>---------------------------------------------------------------------------------------------------<p>So all the interesting work of sys_open() is done in filp_open(). This routine is found in fs/open.c:<p>---------------------------------------------------------------------------------------------------<br>struct file *filp_open(const char *filename, int flags, int mode) {<br> struct nameidata nd;<br> open_namei(filename, flags, mode, &nd);<br> return dentry_open(nd.dentry, nd.mnt, flags);<br>}<br>---------------------------------------------------------------------------------------------------<p>The struct nameidata is defined in include/linux/fs.h. It is used during lookups.<p>---------------------------------------------------------------------------------------------------<br>struct nameidata {<br> struct dentry *dentry;<br> struct vfsmount *mnt;<br> struct qstr last;<br>};<br>---------------------------------------------------------------------------------------------------<p>The routine open_namei() is found in fs/namei.c:<p>---------------------------------------------------------------------------------------------------<br>open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) {<br> if (!(flag & O_CREAT)) {<br> /* The simplest case - just a plain lookup. */<br> if (*pathname == '/') {<br> nd->mnt = mntget(current->fs->rootmnt);<br> nd->dentry = dget(current->fs->root);<br> } else {<br> nd->mnt = mntget(current->fs->pwdmnt);<br> nd->dentry = dget(current->fs->pwd);<br> }<br> path_walk(pathname, nd);<br> /* Check permissions etc. */<br> ...<br> return 0;<br> }<br> ...<br>}<br>---------------------------------------------------------------------------------------------------<p>An inode (index node) describes a file. A file can have several names (or no name at all), but it has a unique inode. A dentry (directory entry)describes a name of a file: the inode plus the pathname used to find it. Avfsmount describes the filesystem we are in.<p>So, essentially, the lookup part op open_namei() is found in path_walk():<p>---------------------------------------------------------------------------------------------------<br>path_walk(const char *name, struct nameidata *nd) {<br> struct dentry *dentry;<br> for(;;) {<br> struct qstr this;<br> this.name = next_part_of(name);<br> this.len = length_of(this.name);<br> this.hash = hash_fn(this.name);<br> /* if . or .. then special, otherwise: */<br> dentry = cached_lookup(nd->dentry, &this);<br> if (!dentry)<br> dentry = real_lookup(nd->dentry, &this);<br> nd->dentry = dentry;<br> if (this_was_the_final_part)<br> return;<br> }<br>}<br>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -