📄 linux可加载内核模块完全版.htm
字号:
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>printk (...) </FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>同用户空间的<FONT size=3>printf</FONT>函数<FONT size=3>
</FONT></P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>void *memset (void *s, char c, size_t count);</P>
<P align=justify>void *memcpy (void *dest, const void *src, size_t
count);</P>
<P align=justify>char *bcopy (const char *src, char *dest, int
count);</P>
<P align=justify>void *memmove (void *dest, const void *src, size_t
count);</P>
<P align=justify>int memcmp (const void *cs, const void *ct, size_t
count);</P>
<P align=justify>void *memscan (void *addr, unsigned char c, size_t
size);</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>内存函数</P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>int register_symtab (struct symbol_table *intab);
</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>见<FONT size=3> I.1 </FONT></P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>char *strcpy (char *dest, const char *src);</P>
<P align=justify>char *strncpy (char *dest, const char *src, size_t
count);</P>
<P align=justify>char *strcat (char *dest, const char *src);</P>
<P align=justify>char *strncat (char *dest, const char *src, size_t
count);</P>
<P align=justify>int strcmp (const char *cs, const char *ct);</P>
<P align=justify>int strncmp (const char *cs,const char *ct, size_t
count);</P>
<P align=justify>char *strchr (const char *s, char c);</P>
<P align=justify>size_t strlen (const char *s);size_t strnlen (const
char *s, size_t count);</P>
<P align=justify>size_t strspn (const char *s, const char
*accept);</P>
<P align=justify>char *strpbrk (const char *cs, const char *ct);</P>
<P align=justify>char *strtok (char *s, const char
*ct);</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>字符串比较函数等等<FONT size=3> </FONT></P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>unsigned long simple_strtoul (const char *cp, char
**endp, unsigned int base); </FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>把字符串转换成数字</P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>get_user_byte (addr);</P>
<P align=justify>put_user_byte (x, addr);</P>
<P align=justify>get_user_word (addr);</P>
<P align=justify>put_user_word (x, addr);</P>
<P align=justify>get_user_long (addr);</P>
<P align=justify>put_user_long (x, addr);</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>访问用户内存的函数</P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>suser();</P>
<P align=justify>fsuser();</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>检测超级用户权限</P></TD></TR>
<TR>
<TD vAlign=top width="60%"><FONT size=3>
<P align=justify>int register_chrdev (unsigned int major, const char
*name, struct file_o perations *fops);</P>
<P align=justify>int unregister_chrdev (unsigned int major, const
char *name);</P>
<P align=justify>int register_blkdev (unsigned int major, const char
*name, struct file_o perations *fops);</P>
<P align=justify>int unregister_blkdev (unsigned int major, const
char *name);</FONT></P></TD>
<TD vAlign=top width="40%">
<P align=justify>登记设备驱动器的函数</P><FONT size=3>
<P align=justify>..._chrdev -> </FONT>字符设备</P><FONT size=3>
<P align=justify>..._blkdev ->
</FONT>块设备</P></TD></TR></TBODY></TABLE></CENTER></DIV>
<P><FONT size=3> </P>
<P align=justify></FONT> </P>
<P align=justify>请记住,这些函数中有的也可用<FONT
size=3>I.5</FONT>中提到的方法实现。当然你也要明白,如果内核已经提供了这些,自己构造就意义不大了。后面你将看到这些函数(尤其是字符串比较)对实现我们的目的非常重要。</P>
<P align=justify><FONT size=4> </P>
<P align=justify>7.</FONT><FONT face=宋体 size=4>什么是内核后台进程</FONT></P>
<P align=justify>最后我们基本到了基础知识部分的结尾,现在我解释一下内核后台进程的运行情形(<FONT
size=3>/sbin/kerneld</FONT>)。从名字可以看到这是一个用户空间中等待某个动作的进程。首先应该知道,为了应用<FONT
size=3>kerneld</FONT>的特点,必须在建立内核时激活<FONT size=3>kerneld</FONT>选项。<FONT
size=3>Kerneld</FONT>按如下方式工作:如果内核想访问某项资源(当然在内核空间),而资源目前没有,它并不产生错误,而是向<FONT
size=3>Kerneld</FONT>请求该项资源。如果<FONT
size=3>kerneld</FONT>能够提供资源,就加载所需的<FONT
size=3>LKM</FONT>,内核继续运行。使用这种模式可以仅当<FONT size=3>LKM</FONT>真正需要<FONT
size=3>/</FONT>不需要时被加载或卸载。很明显这些工作在用户空间和内核空间都有。<FONT size=3></P>
<P
align=justify>Kerneld</FONT>存在于用户空间。如果内核请求一个新模块,这个后台进程将收到一个内核发来的通知哪个模块被加载的字符串。内核可能发送一个一般的名字象<FONT
size=3>eth0</FONT>(而非对象文件),这时系统需要查找<FONT
size=3>/etc/modules.conf</FONT>中的别名行。这些行把系统所需的<FONT
size=3>LKM</FONT>同一般名称匹配起来。</P>
<P align=justify>下行说明<FONT size=3>eth0</FONT>对应<FONT
size=3>DEC</FONT>的<FONT size=3>Tulip </FONT>驱动程序<FONT size=3>LKM</P>
<P align=justify># /etc/modules.conf # </FONT>或<FONT
size=3>/etc/conf.modules – </FONT>反过来<FONT size=3></P>
<P align=justify>alias eth0 tulip</FONT></P>
<P align=justify>以上是对应用户空间由<FONT size=3>kerneld</FONT>后台进程使用的。内核空间主要由<FONT
size=3>4</FONT>个函数对应。这些函数都基于对<FONT
size=3>kernekl_send</FONT>的调用。确切的通过<FONT
size=3>kerneld_send</FONT>调用这些函数的方法可参见<FONT
size=3>linux/kerneld.h</FONT>。下表列出上面提到的四个函数:</P>
<P align=justify> </P>
<P align=center> </P>
<DIV align=center>
<CENTER>
<TABLE cellSpacing=1 cellPadding=7 width=568 border=1>
<TBODY>
<TR>
<TD vAlign=top width="56%">
<P align=center>函数</P></TD>
<TD vAlign=top width="44%">
<P align=center>描述</P></TD></TR>
<TR>
<TD vAlign=top width="56%"><FONT size=3>
<P align=justify>int sprintf (char *buf, const char *fmt, ...);</P>
<P align=justify>int vsprintf (char *buf, const char *fmt, va_list
args);</FONT></P></TD>
<TD vAlign=top width="44%">
<P align=justify>用于把输入数据放入字符串中的函数<FONT size=3> </FONT></P></TD></TR>
<TR>
<TD vAlign=top width="56%"><FONT size=3>
<P align=justify>int request_module (const char *name);
</FONT></P></TD>
<TD vAlign=top width="44%">
<P align=justify>告知<FONT size=3>kerneld</FONT>内核请求某个模块(给出名称或类<FONT
size=3>ID/</FONT>名称)<FONT size=3> </FONT></P></TD></TR>
<TR>
<TD vAlign=top width="56%"><FONT size=3>
<P align=justify>int release_module (const char* name, int
waitflag); </FONT></P></TD>
<TD vAlign=top width="44%">
<P align=justify>卸载模块</P></TD></TR>
<TR>
<TD vAlign=top width="56%"><FONT size=3>
<P align=justify>int delayed_release_module (const char *name);
</FONT></P></TD>
<TD vAlign=top width="44%">
<P align=justify>延迟卸载</P></TD></TR>
<TR>
<TD vAlign=top width="56%"><FONT size=3>
<P align=justify>int cancel_release_module (const char *name);
</FONT></P></TD>
<TD vAlign=top width="44%">
<P align=justify>取消对<FONT size=3>delayed_release_module
</FONT>的调用</P></TD></TR></TBODY></TABLE></CENTER></DIV>
<P> </P>
<P align=justify>注:内核<FONT size=3>2.2</FONT>版用其它模式请求模块。参见第五部分。</P>
<P align=justify><FONT size=4> </P>
<P align=justify>8.</FONT><FONT face=宋体 size=4>建立你自己的设备</FONT></P>
<P align=justify>附录<FONT size=3>A</FONT>介绍了<FONT
size=3>TTY</FONT>截取功能,它用一设备记录结果。所以我们先看一个设备驱动程序的很基本的例子。看如下代码(这是一个最基本的驱动程序,我主要写来演示,它几乎什么也不做):<FONT
size=3></P>
<P align=justify>#define MODULE</P>
<P align=justify>#define __KERNEL__</P>
<P align=justify> </P>
<P align=justify>#include <linux/module.h></P>
<P align=justify>#include <linux/kernel.h></P>
<P align=justify>#include <asm/unistd.h></P>
<P align=justify>#include <sys/syscall.h></P>
<P align=justify>#include <sys/types.h></P>
<P align=justify>#include <asm/fcntl.h></P>
<P align=justify>#include <asm/errno.h></P>
<P align=justify>#include <linux/types.h></P>
<P align=justify>#include <linux/dirent.h></P>
<P align=justify>#include <sys/mman.h></P>
<P align=justify>#include <linux/string.h></P>
<P align=justify>#include <linux/fs.h></P>
<P align=justify>#include <linux/malloc.h></P>
<P align=justify> </P>
<P align=justify>/*</FONT>只用于演示<FONT size=3>*/</P>
<P align=justify>static int driver_open(struct inode *i, struct file
*f)</P>
<P align=justify>{</P>
<P align=justify>printk("<1>Open Function\n");</P>
<P align=justify>return 0;</P>
<P align=justify>}</P>
<P align=justify> </P>
<P align=justify>/*</FONT>登记我们的驱动程序提供的所有函数<FONT size=3>*/</P>
<P align=justify>static struct file_operations fops = {</P>
<P align=justify>NULL, /*lseek*/</P>
<P align=justify>NULL, /*read*/</P>
<P align=justify>NULL, /*write*/</P>
<P align=justify>NULL, /*readdir*/</P>
<P align=justify>NULL, /*select*/</P>
<P align=justify>NULL, /*ioctl*/</P>
<P align=justify>NULL, /*mmap*/</P>
<P align=justify>driver_open, /*open,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -