QQ在线服务: 风舞残阳风舞残阳 年满19岁年满19岁 小罗小罗 晴天晴天 心雨心雨 叮叮肉叮叮肉 小周小周 小童小童 小破孩小破孩 遥望当年遥望当年

用户导购指南

水货IBM笔记本电脑报价

行货IBM笔记本电脑报价

IBM服务器报价

IBM笔记本电脑配件报价

本周水货IBM笔记本电脑特价

IBM笔记本电脑驱动下载

水货IBM笔记本电脑验机流程

水货IBM笔记本电脑保修政策

IBM笔记本电脑FRU查询

IBM笔记本电脑常见问题

IBM笔记本电脑使用手册

笔记本电脑验机软件

论坛积分使用说明

水货IBM笔记本电脑异地购机流程

笔记本电脑购机经历及现场

贵宾申请入口

贵宾用户FTP入口

查看笔记本配置

水货APPLE苹果笔记本电脑报价

 
发新话题
打印

[linux教程] 内核学习FAQ大集锦

内核学习FAQ大集锦

1.请推荐一些好的Linux内核参考书?8 }% [/ C) j' h
a.《LinuxDeviceDrivers,SecondEdition》,有中文译本
; ]' a1 F: {4 Ab.《UnderstandingtheLinuxKernel,2ndEdition》1 S6 o3 B4 q, |$ t
c.《Linux内核源代码情景分析》,分上下两册
2 g. t- }/ g7 z9 `d.《边干边学-Linux内核指导》
: \7 Z% R( O0 p/ M" g6 {- `. S- |  y
, y7 Z" r5 x& ^9 G1 W; ~$ s% a+ `5 ]0 t  f, D# [4 s
2.内核源代码问题
% x, H; E- d. F2.1如何得到某一版本的Linux内核源代码?% K1 P, M3 o* `3 a9 O3 a5 `+ B
a.http://www.kernel.org或ftp://ftp.kernel.org,这是Linux内核版本的发布  Q6 R* c& S6 q) m
网站
! c1 j0 @3 f1 vb.很多镜像或本地网站也提供部分Linux内核版本的下载,多用ftp搜索引擎。
3 B/ e* Z* E& {0 \c.一般的Linux发行版如Redhat会随盘提供相应的内核源代码,不过这个源代
. P- R) m! e; X# \0 F; `% q. i码往往是改动过的,与同版本的标准Linux内核可能有些差异。: B/ R9 m) }; Z' `+ J8 u

3 S3 m1 r  y& u, A2 L6 A" r. T' A2.2请推荐一些源代码查看工具?
, s: M" H8 f5 B" Y! M5 Za.Windows系统可以用SourceInsight,Linux系统可以用SourceNavigator。  A/ ~2 Q9 u  Q2 v. U$ X# U
b.vim或emacs编辑器,配合cscope、ctags、etags等交叉索引工具。
7 K! T  p0 J% Sc.vim或emacs编辑器,配合grep、egrep等文本搜索工具,不过最好要对源代码目4 c7 T* [8 ^+ D6 O  T  C0 V
结构有所熟悉1 O- x3 m; Z  [* {/ `$ L
d.LXR,以网页的形式通过浏览器浏览,安装复杂,可从http://lxr.linux.no/下+ C; Z/ L; d+ \: F8 k* d
载该工具也可以直接访问http://lxr.linux.no/source/在线阅读Linux内核源& E. p) _" E+ v/ U3 p
代码。
$ O6 z. Y; n& g* \( x& Y& r' Z1 l' q+ A' T4 }3 Y4 @1 b
2.3xx结构的定义在哪个内核源文件中?
$ O9 l- I- }" |a.请使用源码查看工具,见问题2.2。
6 N+ t1 P( `9 N! X* ab.如果用grep等文本搜索工具,主要在include/linux和include/asm两个目录下
& ~; [$ y; \( q* |7 Q0 ?搜索。8 B1 F: c8 Y; `& k9 c6 e

/ s. U% E6 g2 G0 Z! D4 D/ I2.4volatile和__volatile__是什么意思?
% C& w$ I6 ~! K5 va.volatile是C语言定义的关键字,gcc为了需要又定义了__volatile__,它和* g* @7 @) \$ L" z( t  ~
volatile表达的是同一意思。
+ V; m9 {5 O+ r3 b. Ib.volatile的本意是"易变的",由于访问寄存器的速度快于访存,所以编译器一般- A, a' R- f/ O- G( Q- v9 l7 ~0 a
都会作优化以减少访存。如果变量加上volatile修饰,则编译器就不会对此变量
% y! Y9 m. l& G% F) i6 W; k2 [- p的读写操作进行优化,即不通过寄存器缓冲而直接访存。
5 X( W* o6 c- P3 B$ T6 g5 N; Uc.__asm____volatile__一起指示编译器不要改动优化后面的汇编语句。
4 }. c7 }0 z0 }* v, E' R6 @) T/ H. p# r* s/ D3 K  h! C' J
2.5do{...}while(0)是什么意思?+ E7 v+ M6 |- S; o! d3 {% p" s
a.主要是为了避免宏在不同情况展开可能会出现的一些错误。# y( C1 Z. w* Z8 I
b.在http://www.kernelnewbies.org/faq/上有详细介绍。
; p9 L4 L+ p8 S: z1 N  w9 l( Z
. x4 K" i. t5 Z7 Z2.6list_entry的定义是怎么回事?
# m3 ?$ p. O3 F  [7 \" W3 @6 _a.list_entry的定义在内核源文件include/linux/list.h中:
" J# v7 y1 P. l. O3 A! l  V+ t#definelist_entry(ptr,type,member)\( r& v% F; `0 V- m3 m+ h) u; n
((type*)((char*)(ptr)-(unsignedlong)(%26((type*)0)-%26gt;member)))1 u1 t) l0 U9 e2 x7 ?
b.其功能是根据list_head型指针ptr换算成其宿主结构的起始地址,该宿主结构是! D9 U: t1 }4 n) y) v# w& r' C* N3 q
type型的,而ptr在其宿主结构中定义为member成员。如下图:  _, `3 Y+ {! s4 H* R; \

. |& _6 E# J3 H  u, S; H% [% breq--%26gt;│type型对象起始地址
1 e% j9 o- R* W" }! \& ?6 }( T: p: b3 R' n0 u! {
│......
. |# d8 p$ ~8 d2 L' ^ptr--%26gt;│ptr指针所指的member成员地址9 R& F& s! h; b( @
. g5 _' a; n% h
│......
; ~' y9 g  ]* a$ s- x+ v+ m  w- N7 d( E$ H4 _$ r' q
ptr指向图中所示的位置,通过(unsignedlong)(%26((type*)0)-%26gt;member)得到ptr* a8 C4 e- j9 S! @: i% R3 H# [" k
和req之间的差值,ptr减去这个差值就得到了type型宿主结构的指针req,返回' a! X7 ]/ m0 y( N* |# s! a  ]+ e4 }
类型为(type*)。
/ v. O( I( b7 e8 }- J3 U: i
2 e. ]9 U- U0 h; Z2 x( D/ }, f1 O* y, ^+ W* I3 ]6 \# {* ?
3.模块编程问题" P6 G" \" o, W: ]( ]' ^$ _( v
3.1模块编程需要注意什么?* {: Z- {& q0 |  U$ ~
a.在gcc编译选项中增加-c
/ V1 [; Z5 }/ D: ~0 D) N7 vb.在gcc编译选项中定义两个宏:-DMODULE-D__KERENL__3 D; A3 S; w' L5 ?9 f0 M" k% f  L6 Z
或直接在源文件中定义这两个宏:
  m1 R9 _2 ?- b8 I. i- @$ T! j0 k#defineMODULE  p* W% C9 f  }. m! t! s. j
#define__KERNEL__- e1 U% l$ {. Y
c.在源文件中包括module.h文件:( y' B  s) n2 s# ^4 b7 a3 d1 ~
#include%26lt;linux/module.h%26gt;) q  E' M5 J" j  J1 |
d.如果要用inline功能,需要在gcc编译选项中增加-O2% E/ ^6 g0 F, w, g
& O/ m8 o' K  x6 B: K* d9 C2 n
3.2为什么insmod一个模块时显示版本不匹配?
: i3 D. `5 c9 V2 h6 k假定你现在运行的内核的源码目录绝对路径是MyKernelSrcPath,在gcc编译时
" C1 g; n& O8 E% R) w5 k5 ?  Z增加选项:$ p* d) O& p3 D3 ~4 ^" X# z1 R) K
-I$MyKernelSrcPath/include1 @! v0 L+ D- A, k3 K8 ^0 l
" P% B3 J. N: Y) K
3.3为什么出现UnresolvedSymbol?
% y! m0 h* @4 o. Ca.首先查看文件/proc/ksyms,看内核有没有输出这个符号,不同的内核版本如3 D5 U" s7 f# B
2.2和2.4输出的符号会有些变化。% D# \6 \' \. b
b.如果内核输出的符号带有版本控制信息如符号printk_R12345678,则性质同
" `5 d" h8 t' p; }; H2 ?3 j, f问题3.2。9 F7 g3 T5 R( Z' {) K; i
( o" \  ]+ d: Z6 h2 O" F
3.4为什么出现nolicense错误?
# s9 S% b) Y& r) z在源文件加入下面一行:
; I0 L9 o4 }" h% E" NMODULE_LICENSE("GPL");5 ]2 y- ~* N# ~& L( K. ?- D2 y+ ]
" W6 i" W# F5 k' i, v
3.5为什么看不到用printk打印的信息?7 z( s3 A! D* {# h
a.打印消息受级别的限制,消息级别可以通过printk设置,如:
2 G% R% P/ _1 s& \4 O9 h' \* X+ Z& Wprintk("%26lt;n%26gt;something");/*其中0%26lt;=n%26lt;=7*/
" h; X8 q, a3 ~% h- O假设控制台的消息级别为m,当n%26lt;m时消息打印到控制台,否则不打印。
# D/ `+ p$ m2 B- s9 F这样一方面可以提高要打印消息本身的级别(数字越小级别越高),6 S% j/ X$ L% a  V6 E+ r5 W
另一方面可以改变控制台的消息级别(可从1到8),如改为8可用以下命令:4 e: Z. W3 A' j1 G: K0 l
#echo"8"%26gt;/proc/sys/kernel/printk# [& e/ Z* Y# V: Q$ M+ y
b.用dmesg命令看。
8 v; }% A" b! l# y9 Pc.当系统运行klogd和syslogd时,内核消息就会由klogd分发到syslogd,
$ v, j, }+ Q' y5 t$ Q  Z/ H" isyslogd会根据配置文件/etc/syslog.conf作相应处理,具体可以查看syslogd9 i% H0 j9 h6 o0 ]0 N+ y
和syslog.conf的man页。
5 o9 S% F# @# u$ G! _# F' w# a& R% x, U
$ G( q' J3 W1 }
4.内核开发问题$ z- p/ z$ O& ?% Y
4.1怎么制作、使用patch文件?. r7 q0 [( ~* s
patch文件是由diff命令生成的,使用patch文件用patch命令,具体可查看diff和
7 r' @6 v0 E% P$ A4 ?9 g% {8 v/ Opatch的man页和info。
- x/ y) b: n' A7 J) L3 S% g
, p/ @# d4 w" C0 j+ v4.2在内核中可以使用系统调用吗?
- h" X% I( ]3 e2 }: f6 L1 ca.可以。内核源代码中就有使用系统调用的例子,如open()、execve()等。
; I( i) o$ x8 k0 b" s( B; yb.在内核中使用系统调用必须要在源文件中包括以下两行:
$ T- I# @- J; H9 c#define__KERNEL_SYSCALLS__
+ w9 N7 r. H. Z8 B3 ^+ L#include%26lt;linux/unistd.h%26gt;! E; F, r' g8 S# A3 M
c.内核中使用系统调用的相关定义可查看文件include/asm/unistd.h。# e/ ], I' O+ ~
如果要用的系统调用该文件中没有定义,可以按照其格式自行添加。8 L3 e/ |0 C4 K( \7 \6 o
1 e/ q7 f% o0 N: ?7 h) j3 e  G
4.3在内核中怎么打开并操作一个文件?1 l9 A+ n1 L+ D+ `2 o5 i5 @
a.直接用open()、read()等系统调用,见问题4.2。% w6 _' e, Z5 t
b.用filp_open()函数打开文件,得到structfile*的指针fp。
& N  i2 V! o  ^& n" Q0 j使用指针fp进行相应操作,如读文件可以用fp-%26gt;f_ops-%26gt;read。4 _2 u7 l5 j3 q5 ~# t2 t( h
最后用filp_close()函数关闭文件。
/ w( ~5 i( `" e' B% a- Q0 |. ofilp_open()、filp_close()函数在fs/open.c定义,在include/linux/fs.h中
! p! M8 D. @! R+ \& V% u声明。( U8 [( l% ~/ O: Z
c.自己写包装函数,可参照文件fs/exec.c中的open_exec()和kernel_read()函数。  D) }+ s2 B4 q
在http://www.linuxforum.net/forum/showflat.php?Cat=%26Board=linuxK
  q" Q% [, M# n* e5 J+ b%26Number=363455%26page=%26view=%26sb=%26o=%26vc=1上有些代码可以参照。! {" n7 j1 t# P( w# d
* ?1 F7 t' o5 D
4.4在内核中读写文件时为什么会出现EFAULT错误?) g/ U4 J8 o7 l! f! R4 O0 C1 @
a.内核文件系统提供的read()和write()之类的函数,期望是对用户态程序服务的,- i9 O) ?  P1 V$ P
所以它会验证读写缓冲区不超过用户空间的上限即0xC0000000。但现在内核中
9 U: e( q6 H/ W要读写文件,缓冲区在内核中即地址会超过0xC0000000。' b0 {& ^. N9 V5 ]1 c# M- k! p- l
b.在读写文件前先得到当前fs:mm_segment_told_fs=get_fs();
# s* o+ m# @' r! F) ~并设置当前fs为内核fs:set_fs(KERNEL_DS);
% o4 n+ k0 i: ?5 g在读写文件后再恢复原先fs:set_fs(old_fs);
! J: j" \4 I" P3 v( {set_fs()、get_fs()等相关宏在文件include/asm/uaccess.h中定义。9 j/ l- i/ t  C2 Q7 ~
: m- n8 a  E9 p
" a4 q$ b# Q- t' }
5.其它4 O$ p7 E# Q; C* I

) x' e: D: O3 p. {, }5 ?0 D5.1请问xx命令、xx库的源码是哪个文件?
" y1 F" ^0 J8 Z/ ^a.一个系统除了内核以外,还需要有shell、gcc等一系列工具和命令以及C库等一( W( C% z; J) \5 C; b4 B
系列库,这些作为应用程序其源代码都不在内核中,需要另外下载相应的源代码。
( k% V2 g2 i4 b! c# @! ?b.对于Redhat系统,可以用rqm-qf命令来查找某一命令所在的软件包,然后再找" Z& {9 c) j  s/ q+ _9 B
相应的源代码包安装。
(※本文搜集自:重庆未来科技 http://www.wlkj.net 重庆IBM笔记本电脑、重庆IBM水货笔记本电脑、重庆苹果笔记本电脑、重庆IBM服务器专卖)

TOP

发新话题