Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1945444
  • 博文数量: 383
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 4061
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-24 18:53
文章分类

全部博文(383)

文章存档

2011年(1)

2010年(9)

2009年(276)

2008年(97)

我的朋友

分类: LINUX

2008-11-12 21:15:01

1. 请推荐一些好的Linux内核参考书?
a.《Linux Device Drivers, Second Edition》,有中文译本
b.《Understanding the Linux Kernel, 2nd Edition》
c.《Linux内核源代码情景分析》,分上下两册
d.《边干边学-Linux内核指导》


2. 内核源代码问题
2.1 如何得到某一版本的Linux内核源代码?
a.
,这是Linux内核版本的发布
网站。
b. 很多镜像或本地网站也提供部分Linux内核版本的下载,多用ftp搜索引擎。
c. 一般的Linux发行版如Redhat之类会随盘提供相应的内核源代码,不过这个源代
码往往是改动过的,与同版本的标准Linux内核可能有些差异。

2.2 请推荐一些源代码查看工具?
a. Windows系统可以用Source Insight,Linux系统可以用Source Navigator。
b. vim或emacs编辑器,配合cscope、ctags、etags等交叉索引工具。
c. vim或emacs编辑器,配合grep、egrep等文本搜索工具,不过最好要对源代码目
录结构有所熟悉
d. LXR,以网页的形式通过浏览器浏览,安装复杂,可从

载该工具也可以直接访问
在线阅读Linux内核源
代码。

2.3 xx结构的定义在哪个内核源文件中?
a. 请使用源码查看工具,见问题2.2。
b. 如果用grep等文本搜索工具,主要在include/linux和include/asm两个目录下
搜索。

2.4 volatile和__volatile__是什么意思?
a. volatile是C语言定义的关键字,gcc为了需要又定义了__volatile__,它和
volatile表达的是同一意思。
b. volatile的本意是"易变的",由于访问寄存器的速度快于访存,所以编译器一般
都会作优化以减少访存。如果变量加上volatile修饰,则编译器就不会对此变量
的读写操作进行优化,即不通过寄存器缓冲而直接访存。
c. __asm__ __volatile__一起指示编译器不要改动优化后面的汇编语句。

2.5 do{ ... } while(0)是什么意思?
a. 主要是为了避免宏在不同情况展开可能会出现的一些错误。
b. 在
上有详细介绍。

2.6 list_entry的定义是怎么回事?
a. list_entry的定义在内核源文件include/linux/list.h中:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
b. 其功能是根据list_head型指针ptr换算成其宿主结构的起始地址,该宿主结构是
type型的,而ptr在其宿主结构中定义为member成员。如下图:

req>|type型对象起始地址
|
|... ...
ptr>|ptr指针所指的member成员地址
|
|... ...

ptr指向图中所示的位置,通过(unsigned long)(&((type*)0)->member)得到ptr
和req之间的差值,ptr减去这个差值就得到了type型宿主结构的指针req,返回
类型为(type*)。


3. 模块编程问题
3.1 模块编程需要注意什么?
a. 在gcc编译选项中增加-c
b. 在gcc编译选项中定义两个宏:-DMODULE -D__KERENL__
或直接在源文件中定义这两个宏:
#define MODULE
#define __KERNEL__
c. 在源文件中包括module.h文件:
#include
d. 如果要用inline功能,需要在gcc编译选项中增加-O2

3.2 为什么insmod一个模块时显示版本不匹配?
假定你现在运行的内核的源码目录绝对路径是MyKernelSrcPath,在gcc编译时
增加选项:
-I $MyKernelSrcPath/include

3.3 为什么出现Unresolved Symbol?
a. 首先查看文件/proc/ksyms,看内核有没有输出这个符号,不同的内核版本如
2.2和2.4输出的符号会有些变化。
b. 如果内核输出的符号带有版本控制信息如符号printk_R12345678,则性质同
问题3.2。

3.4 为什么出现no license错误?
在源文件加入下面一行:
MODULE_LICENSE("GPL");

3.5 为什么看不到用printk打印的信息?
a. 打印消息受级别的限制,消息级别可以通过printk设置,如:
printk("something"); /* 其中0<=n<=7 */
假设控制台的消息级别为m, 当n 这样一方面可以提高要打印消息本身的级别(数字越小级别越高),
另一方面可以改变控制台的消息级别(可从1到8),如改为8可用以下命令:
# echo "8" > /proc/sys/kernel/printk
b. 用dmesg命令看。
c. 当系统运行klogd和syslogd时,内核消息就会由klogd分发到syslogd,
syslogd会根据配置文件/etc/syslog.conf作相应处理,具体可以查看syslogd
和syslog.conf的man页。


4. 内核开发问题
4.1 怎么制作、使用patch文件?
patch文件是由diff命令生成的,使用patch文件用patch命令,具体可查看diff和
patch的man页和info。

4.2 在内核中可以使用系统调用吗?
a. 可以。内核源代码中就有使用系统调用的例子,如open()、execve()等。
b. 在内核中使用系统调用必须要在源文件中包括以下两行:
#define __KERNEL_SYSCALLS__
#include
c. 内核中使用系统调用的相关定义可查看文件include/asm/unistd.h。
如果要用的系统调用该文件中没有定义,可以按照其格式自行添加。

4.3 在内核中怎么打开并操作一个文件?
a. 直接用open()、read()等系统调用,见问题4.2。
b. 用filp_open()函数打开文件,得到struct file *的指针fp。
使用指针fp进行相应操作,如读文件可以用fp->f_ops->read。
最后用filp_close()函数关闭文件。
filp_open()、filp_close()函数在fs/open.c定义,在include/linux/fs.h中
声明。
c. 自己写包装函数,可参照文件fs/exec.c中的open_exec()和kernel_read()函数。

&Number=363455&page=&view=&sb=&o=&vc=1上有些代码可以参照。

4.4 在内核中读写文件时为什么会出现EFAULT错误?
a. 内核文件系统提供的read()和write()之类的函数,期望是对用户态程序服务的,
所以它会验证读写缓冲区不超过用户空间的上限即0xC000 0000。但现在内核中
要读写文件,缓冲区在内核中即地址会超过0xC000 0000。
b. 在读写文件前先得到当前fs:mm_segment_t old_fs=get_fs();
并设置当前fs为内核fs:set_fs(KERNEL_DS);
在读写文件后再恢复原先fs: set_fs(old_fs);
set_fs()、get_fs()等相关宏在文件include/asm/uaccess.h中定义。


5. 其它

5.1 请问xx命令、xx库的源码是哪个文件?
a. 一个系统除了内核以外,还需要有shell、gcc等一系列工具和命令以及C库等一
系列库,这些作为应用程序其源代码都不在内核中,需要另外下载相应的源代码。
b. 对于Redhat系统,可以用rqm -qf命令来查找某一命令所在的软件包,然后再找
相应的源代码包安装。
阅读(505) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~