|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
. ?& S9 V( y/ A6 A! {5 j$ j5 L
在尝试内核开发之前,需要对内核有个整体的了解。
7 o: @) }! s6 {6 D! l1 Y0 V' ]% [2 w
主要内容:
' b! ?2 X6 p: b7 o% O8 Z- o ?( q. |( O
获取内核源码
% D3 L, R8 v5 {0 x" k+ c内核源码的结构$ g O# y' E" a; D) V8 X
编译内核的方法
/ ?9 `- h% `3 D/ j5 ?* B) s内核开发的特点/ C i4 q% y* D& d
& E+ w! h0 O9 X& J. ]( o; t/ R- s, e
7 d- l% Q0 R/ Y* O6 l9 o/ E! _1. 获取内核源码4 y; `- m7 \4 { T
内核是开源的,所有获取源码特别方便,参照以下的网址,可以通过git或者直接下载压缩好的源码包。4 b( i \% D4 a1 | H+ h
+ T/ [4 `7 u! p$ S! ?
http://www.kernel.org7 N! q+ ?# u4 |( \8 l
/ s( ~. Q3 O9 Q, v- O
5 h4 U, E! p( J8 Z8 d5 x6 a$ U7 K: b7 b4 d" B x& a7 a
2. 内核源码的结构
$ o/ d# Q* r' \+ O6 k
5 v' F* y* Z, R. f/ U
# d6 b% B* I4 Z6 ]目录 说明& K2 B7 v% s5 q
arch 特定体系结构的代码
# k$ f+ O0 M! V+ Wblock 块设备I/O层& |2 N9 q1 s# ?, b' F, F, v A
crypo 加密API5 l/ Y; C/ C4 p7 R6 `$ D$ e3 J' ?
Documentation 内核源码文档" f5 I; y$ P! M+ K3 }' Y3 K
drivers 设备驱动程序; t |4 G0 }$ n f5 L& C
firmware 使用某些驱动程序而需要的设备固件( U# f4 @7 l5 D' Q& W9 k
fs VFS和各种文件系统
$ O U1 ?+ X" einclude 内核头文件
) p$ ?3 M4 _% b5 K! n9 |) iinit 内核引导和初始化
8 Q7 ~1 h' q* @4 U: w5 `9 Eipc 进程间通信代码/ `# ~( X# P0 ]4 q. E+ }5 V# _
kernel 像调度程序这样的核心子系统- F* U1 Z$ K8 I, t
lib 同样内核函数6 r" w7 C* u( G- D- n% {
mm 内存管理子系统和VM- @# a& c6 N8 \
net 网络子系统
8 _- \5 R1 E- o& v0 |samples 示例,示范代码
( G% F0 ~, L1 a5 R( Bscripts 编译内核所用的脚本
- `, f1 t2 S$ [0 }security Linux 安全模块
" q& @1 b9 \7 j& [1 lsound 语音子系统0 e, Z7 C7 V, X1 l+ n
usr 早期用户空间代码(所谓的initramfs)% u' }" P) S2 y0 T! _
tools 在Linux开发中有用的工具1 f0 ]* _* P i! J, T8 I' }& S! I
virt 虚拟化基础结构
& B. l0 j3 y; T ' P% d3 ^# J: J y1 ]' W% i
2 ~* U% i, n* |" s5 B
3. 编译内核的方法
, i1 g, [5 {( y3 H- z. w还未实际尝试过手动编译内核,只是用yum更新过内核。这部分等以后手动编译过再补上。
_& w) S, Z7 C6 O, `8 n$ m
$ d) Y$ h3 r3 }5 G7 g安装新的内核后,重启时会提示进入哪个内核。当多次安装新的内核后,启动列表会很长(因为有很多版本的内核),显得不是很方便。2 E# y+ _$ l4 o
: T7 E& n( j8 ^! Q! r下面介绍3种删除那些不用的内核的方法:(是如何安装的就选择相应的删除方法)/ e, R. d; s& f/ r
8 Z( f* }' e$ P" P y. c3.1 rpm 删除法
2 L* o% y. O2 s+ t$ a8 g rpm -qa | grep kernel* (查找所有linux内核版本)4 [, k4 k- }+ W! [
rpm -e kernel-(想要删除的版本)
! F: C7 S: |$ l: i6 d+ S K* E
$ M, t6 B7 g, }4 z5 |, k c; y: ?3.2 yum 删除法
; x# q4 c% y( `6 ~ yum remove kernel-(要删除的版本)
1 f+ Z4 t4 w4 C1 W2 q" f3 [) a5 C) J6 h w( g7 }7 q
3.3 手动删除
; i! [8 r; a3 [! Z 删除/lib/modules/目录下不需要的内核库文件
8 n. O# P; t/ v# } 删除/usr/src/kernel/目录下不需要的内核源码6 K3 i0 F: M& l! o; n% K
删除/boot目录下启动的核心档案禾内核映像
$ R# Q4 V1 u! ^* A) B+ f6 c 更改grub的配置,删除不需要的内核启动列表9 y0 M1 I! y/ K
. v' l5 l0 w. Y5 ~* a
1 j6 x! P/ L7 s/ \* A
' Z4 U2 ^# s/ o9 k
4. 内核开发的特点, ~2 [( H3 r. O" W
4.1 无标准C库" P9 Z$ [# ?- x
为了保证内核的小和高效,内核开发中不能使用C标准库,所以连最常用的printf函数也没有,但是还好有个printk函数来代替。4 k1 L" A+ }+ w: ?! m' f/ O5 L' \
2 d8 L* i3 I+ m2 b U4.2 使用GNU C,推荐用gcc 4.4或以后的版本来编译内核
9 p; V, c; i+ W5 z9 R# x" V! ~7 ?因为使用GNU C,所有内核中常使用GNU C中的一些扩展:6 `" c, f9 m# K3 }4 [
* O7 }9 J" H, H8 V6 F& r0 {* `4.2.1 内联函数
# [: }0 y/ O' [' g9 }内联函数在编译时会在它被调用的地方展开,减少了函数调用的开销,性能较好。但是,频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。/ M$ E3 Y) ^% F$ C# _
1 `1 x0 J0 O! x9 u
所以内联函数使用时最好要满足以下几点:函数较小,会被反复调用,对程序的时间要求比较严格。
% \4 F7 ~& l; C! e' n% E( x
# B5 G7 j( z' R2 I3 O内联函数示例:static inline void sample();
2 Q; l- Z4 t. J1 g" j
& e' L- i$ G" z/ S! w2 w; A4.2.2 内联汇编
) |4 v; A e8 v内联汇编用于偏近底层或对执行时间严格要求的地方。示例如下:+ [4 _/ d" C/ v
9 K& `9 w6 ]$ j( W% ~unsigned int low, high;
1 L9 B* V. g2 F1 O1 tasm volatile("rdtsc" : "=a" (low), "=d" (high));3 M n9 h. {# |3 q. H
/* low 和 high 分别包含64位时间戳的低32位和高32位 */
. {* I6 P3 ~+ p/ ^, `- m5 Z4.2.3 分支声明. m. _( V; I/ k) v% }
如果能事先判断一个if语句时经常为真还是经常为假,那么可以用unlikely和likely来优化这段判断的代码。
! {$ Z% D ^/ P* r# `+ K. J9 a
* j% O& T, F/ Y/ R, }# O0 A复制代码
' f$ ~2 M: j- W) D5 U9 m2 o/* 如果error在绝大多数情况下为0(假) */
9 F# j4 n: \3 r/ Q7 k, o: aif (unlikely(error)) { ?. Q9 G7 L7 H5 e4 s
/* ... */
8 D7 J3 j6 H! J4 }$ G, Q}
) l$ w( G$ q& Y) K* Q' k8 \1 l6 x' x1 J& v* y3 C" p* `
/* 如果success在绝大多数情况下不为0(真) */( v5 u# o' d6 M# A
if (likely(success)) {; i N: g9 z! z6 A$ E* l% V! k
/* ... */
" `# C6 A7 ]* v5 {+ G, G/ F+ _6 m3 v}1 @: g* X4 y" J- E% M& P
复制代码# r% F6 o& y4 j* x
4.3 没有内存保护' H! I. |2 E$ `7 E, |! E1 V
因为内核是最低层的程序,所以如果内核访问的非法内存,那么整个系统都会挂掉!!所以内核开发的风险比用户程序开发的风险要大。
* {5 ` {0 ?: N; H
- O- c4 y4 L1 Y+ z而且,内核中的内存是不分页的,每用一个字节的内存,物理内存就少一个字节。所以内核中使用内存一定要谨慎。
# p! J* }* X, S6 t
3 w$ z& u3 ^6 `: D- h$ m4.4 不使用浮点数! k1 }5 J* e& W5 f. G9 c
内核不能完美的支持浮点操作,使用浮点数时,需要人工保存和恢复浮点寄存器及其他一些繁琐的操作。
" V, o4 z |) B2 r3 `# u- j/ L3 v0 B# x1 O& o/ n$ N4 {
4.5 内核栈容积小且固定( `' \( U6 P. Y( t; j9 t
内核栈的大小有编译内核时决定的,对于不用的体系结构,内核栈的大小虽然不一样,但都是固定的。; A& G# q7 D2 d: p1 c7 J# s
1 a! r3 w1 F I+ J
查看内核栈大小的方法:% i4 p! }: U& o$ @. [1 r7 ~4 I
/ p h9 d [3 s z: r
ulimit -a | grep "stack size"* P& f8 R' S9 l/ }3 G2 u
4.6 同步和并发9 ]7 H) G! q$ @ E3 S H
Linux是多用户的操作系统,所以必须处理好同步和并发操作,防止因竞争而出现死锁。
6 \* x9 M: t5 Y% l. N) R& x8 \$ t r) Q" P% c/ `4 d8 B
4.7 可移植性
! q" Y7 D3 S# |4 n) ~Linux内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。 |
|