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

📄 9.html

📁 网上一个牛人整理的关于linux内核编译
💻 HTML
📖 第 1 页 / 共 5 页
字号:
$gcc -o test test.c<br>
$./test<br>
Please input a number<p>
36<br>
Total from 0 to 36 is 666<p>
&nbsp;&nbsp;&nbsp; 可见,修改成功;<p>
&nbsp;&nbsp;&nbsp; 而且,对相关源码的进一步分析可知,在此版本的内核中,从/usr/src/linux/arch/i386/kernel/entry.S<p>
&nbsp;&nbsp;&nbsp; 文件中对 sys_call_table 表的设置可以看出,有好几个系统调用的服务例程都是定义在/usr/src/linux/kernel/sys.c 中的同一个函数:<p>
asmlinkage int sys_ni_syscall(void)<br>
{<br>
return -ENOSYS;<br>
}<p>
&nbsp;&nbsp;&nbsp; 例如第188项和第189项就是如此:<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>
&nbsp;&nbsp;&nbsp; 而这两项在文件 /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>
&nbsp;&nbsp;&nbsp; 由此可见,在此版本的内核源代码中,由于asmlinkage int sys_ni_syscall(void) 函数并不进行任何操作,所以包括 getpmsg, putpmsg 在内的好几个系统调用都是不进行任何操作的,即有待扩充的空调用; 但它们却仍然占用着sys_call_table表项,估计这是设计者们为了方便扩充系统调用而安排的; 所以只需增加相应服务例程(如增加服务例程getmsg或putpmsg),就可以达到增加系统调用的作用。


<center><A HREF="#Content">[目录]</A></center>
<hr><br><A NAME="I481" ID="I481"></A><center><b><font size=+2>一个简单程序的分析----深至内核</font></b></center><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A small trail through the Linux kernel<p>
Andries Brouwer, aeb@cwi.nl 2001-01-01<p>
A program<br>
---------------------------------------------------------------------------------------------------<br>
#include &lt;unistd.h&gt;<br>
#include &lt;fcntl.h&gt;<br>
int main(){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fd;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char buf[512];<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd = open(&quot;/dev/hda&quot;, O_RDONLY);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd &gt;= 0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read(fd, buf, sizeof(buf));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *tmp = getname(filename);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fd = get_unused_fd();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct file *f = filp_open(tmp, flags, mode);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd_install(fd, f);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; putname(tmp);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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()&nbsp;&nbsp;&nbsp;&nbsp; kmem_cache_alloc(names_cachep, SLAB_KERNEL)<br>
#define putname(name)&nbsp;&nbsp; kmem_cache_free(names_cachep, (void *)(name))<p>
char *getname(const char *filename) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *tmp = __getname();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* allocate some memory */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strncpy_from_user(tmp, filename, PATH_MAX + 1);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct files_struct *files = current-&gt;files;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fd = find_next_zero_bit(files-&gt;open_fds,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; files-&gt;max_fdset, files-&gt;next_fd);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET(fd, files-&gt;open_fds);&nbsp;&nbsp;&nbsp; /* in use now */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; files-&gt;next_fd = fd + 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct files_struct *files = current-&gt;files;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; files-&gt;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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct nameidata nd;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; open_namei(filename, flags, mode, &amp;nd);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dentry *dentry;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct vfsmount *mnt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!(flag &amp; O_CREAT)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* The simplest case - just a plain lookup. */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (*pathname == '/') {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nd-&gt;mnt = mntget(current-&gt;fs-&gt;rootmnt);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nd-&gt;dentry = dget(current-&gt;fs-&gt;root);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nd-&gt;mnt = mntget(current-&gt;fs-&gt;pwdmnt);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nd-&gt;dentry = dget(current-&gt;fs-&gt;pwd);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path_walk(pathname, nd);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Check permissions etc. */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dentry *dentry;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(;;) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qstr this;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = next_part_of(name);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.len = length_of(this.name);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.hash = hash_fn(this.name);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* if . or .. then special, otherwise: */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dentry = cached_lookup(nd-&gt;dentry, &amp;this);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dentry)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dentry = real_lookup(nd-&gt;dentry, &amp;this);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nd-&gt;dentry = dentry;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this_was_the_final_part)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>

⌨️ 快捷键说明

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