找回密码
 注册
关于网站域名变更的通知
查看: 264|回复: 1
打印 上一主题 下一主题

Linux内核设计与实现之内核开发的准备

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-9-24 15:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

7 ^# H2 o% b5 v2 y$ o+ D在尝试内核开发之前,需要对内核有个整体的了解。" {, k* d- `# W9 h
# j5 J6 ~9 D& y, ~4 W% s
主要内容:
. A" [. a. s3 ?# o" S( I
; e' A' ?# K+ X( A' s1 L! _8 {  u' a获取内核源码
1 H; Y* m4 _$ V: L$ g) o3 l( T内核源码的结构
" A. c- C- P4 `编译内核的方法) m8 K5 B) M6 [" U0 O
内核开发的特点
  m9 A7 \* h5 B8 Q
& f# o" Y) Q* U' t( h7 f
" {# c, M+ W# o: p4 n1. 获取内核源码
+ H% X, K' H' s: Q内核是开源的,所有获取源码特别方便,参照以下的网址,可以通过git或者直接下载压缩好的源码包。
" i" f* b$ V0 y) n8 |; {& d  p* o
http://www.kernel.org+ L8 V4 z/ ^) L" i2 l
1 Y$ K/ a) h/ U. S6 V+ G) n

  T  j5 w; u1 O7 A. `& J5 }, R% [$ U" q% Q; f
2. 内核源码的结构
7 b  x; f! Z, z   k) N5 ^1 z9 f, J- q& {
7 R, S$ f$ a: @$ y. J8 Z
目录        说明8 L# B3 X: `& C; H2 h0 Z
arch        特定体系结构的代码# S! X& g# d  N& _& }2 w/ u" x' O
block        块设备I/O层
$ `7 P; w- L: p3 Z3 hcrypo        加密API( S- u2 C. n9 A: y" N
Documentation        内核源码文档. m* h- d9 ~' h1 [2 `' [: M6 |
drivers        设备驱动程序
: r! I' U+ k. efirmware        使用某些驱动程序而需要的设备固件) |4 J3 Q( W. J! I. M' A8 K
fs        VFS和各种文件系统
5 s& U! g, e! i7 Iinclude        内核头文件
) z# j) a0 u6 v5 i8 binit        内核引导和初始化# V3 I7 J( a4 X2 m5 `, j
ipc        进程间通信代码
$ a$ t, O' q! ]6 \7 D$ ~! zkernel        像调度程序这样的核心子系统
% C+ N5 E$ o* {4 A' p1 _lib        同样内核函数& k* N. i1 O3 L( u9 ]
mm        内存管理子系统和VM
& t( n- _2 H+ Z& b7 Mnet        网络子系统" W8 l+ \( A" w5 ?  ]; f3 D4 d
samples        示例,示范代码1 I- M. h! W- K' _/ ?
scripts        编译内核所用的脚本
% P) ^$ E) e( Q2 i3 J$ E. ?0 r) |# `security        Linux 安全模块( U& S7 s5 D9 O, y( I
sound        语音子系统! i" Q5 y' ]9 P5 R5 j
usr        早期用户空间代码(所谓的initramfs)
+ H) N7 ]) ~- _tools        在Linux开发中有用的工具7 u* J) ?" U% s: m& k" m; T
virt        虚拟化基础结构
3 ]3 M7 E: u# B2 J% _! d5 T" G( q& w * t5 L6 u7 `2 P9 E) _9 d

  q" R" r  u* T- f3. 编译内核的方法
! G9 R' O, M3 A  M6 Y. V0 t还未实际尝试过手动编译内核,只是用yum更新过内核。这部分等以后手动编译过再补上。5 ?' P( t2 A* L
! @; A) }4 W) ?7 z
安装新的内核后,重启时会提示进入哪个内核。当多次安装新的内核后,启动列表会很长(因为有很多版本的内核),显得不是很方便。
. N4 X" Q5 X& A# m
, f. b, I: G3 X) A, S下面介绍3种删除那些不用的内核的方法:(是如何安装的就选择相应的删除方法)! [( L9 m2 R7 _
/ {1 z+ ~+ P) z6 |2 L6 F% h
3.1 rpm 删除法
" H7 F) `  C' S- Q( R   rpm -qa | grep kernel*  (查找所有linux内核版本)
: a  ?0 ^% r6 e# U5 _2 s7 c   rpm -e kernel-(想要删除的版本)
& c% w$ Y2 L/ h! s2 G' E6 x+ m! M" u; |# y( E& J8 N
3.2 yum 删除法
0 q3 e7 o8 k# i   yum remove kernel-(要删除的版本)) \9 K( n/ ]6 H. L$ n9 q7 x; h

6 t9 z5 d" |8 C7 j' M4 K$ [; h3.3 手动删除
! }+ w! `4 d$ h% u   删除/lib/modules/目录下不需要的内核库文件/ f0 l: U% A& m' ~3 u9 ~
   删除/usr/src/kernel/目录下不需要的内核源码2 m; O8 L0 ?  ]  S4 A3 U
   删除/boot目录下启动的核心档案禾内核映像+ O2 t7 C" d7 I2 [( Q3 u& x4 W
   更改grub的配置,删除不需要的内核启动列表
0 N! F% H/ b* y( E' f; W- d' n5 Y' _! y6 H
2 G; l% G# u$ L6 t7 F

( ~/ v5 E: d& L4. 内核开发的特点, V3 {2 d1 H* }9 S  [( O
4.1  无标准C库7 B8 k- ~- v( s* C1 c; U& r
为了保证内核的小和高效,内核开发中不能使用C标准库,所以连最常用的printf函数也没有,但是还好有个printk函数来代替。
2 C0 S6 |! y0 `/ J
2 Q$ q8 n$ s, K( V. o4.2 使用GNU C,推荐用gcc 4.4或以后的版本来编译内核2 {! N8 |4 c" i
因为使用GNU C,所有内核中常使用GNU C中的一些扩展:8 \, E9 b6 m$ ~5 u" k  I* B
$ T- U# W: |- |: A$ j8 e* s* n9 Q
4.2.1 内联函数3 y4 E; E( c9 F3 l
内联函数在编译时会在它被调用的地方展开,减少了函数调用的开销,性能较好。但是,频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。0 G# r# y: ~* @
, J4 b( r8 R" }6 T
所以内联函数使用时最好要满足以下几点:函数较小,会被反复调用,对程序的时间要求比较严格。
8 K7 C1 G2 M! b% H1 c* F1 ]5 e8 b
内联函数示例:static inline void sample();
# A0 @& V8 B- s- W( {' V/ V
4 w- ?0 z( r. e5 H8 a. V3 E9 m4.2.2 内联汇编
" M8 D. o3 Q" R7 d/ C; c内联汇编用于偏近底层或对执行时间严格要求的地方。示例如下:& d& o, |% {9 q9 l4 q! i8 z

# I  ]1 G- \4 n. Z3 Junsigned int low, high;8 O$ }1 m5 ]+ B; u+ a. z$ I3 Z
asm volatile("rdtsc" : "=a" (low), "=d" (high));* p) o+ A; ?& e9 I9 S) q2 e% u
/* low 和 high 分别包含64位时间戳的低32位和高32位 */) Z# [0 W8 ~9 ~# J, e* ?  _
4.2.3 分支声明% C' D- I+ W# A
如果能事先判断一个if语句时经常为真还是经常为假,那么可以用unlikely和likely来优化这段判断的代码。
! \6 V. k3 R' M, o$ ]4 ~/ ~. W+ B' g& ?
复制代码+ ^7 D+ p& J& F4 X
/* 如果error在绝大多数情况下为0(假) */
6 E9 }7 f5 J, P% w3 }4 Jif (unlikely(error)) {
% l% L! d/ {8 O5 m- A% q: b/ c$ N    /* ... */. T( X6 F" N8 t' x, i- L& h
}
, V3 }" `0 w! W+ M" c, V8 o" l2 j9 q" N) J& N* L
/* 如果success在绝大多数情况下不为0(真) */
! K+ ?  u6 g* W9 r2 `if (likely(success)) {
* f2 k% v6 i) Z  W0 t) O    /* ... */' J( X: d6 ~3 S2 Z$ \. J" g" o+ j" z
}
* v5 e1 g: _5 b. H! a复制代码
) L$ @! Q8 w% N/ w' L4.3 没有内存保护  c& N$ i; E) S' b3 C: H7 \9 D
因为内核是最低层的程序,所以如果内核访问的非法内存,那么整个系统都会挂掉!!所以内核开发的风险比用户程序开发的风险要大。" D5 K5 k# P6 P1 F2 u$ A; @
8 J9 e8 _+ C# j$ j2 B
而且,内核中的内存是不分页的,每用一个字节的内存,物理内存就少一个字节。所以内核中使用内存一定要谨慎。, X7 T) x4 v, {5 d4 L+ q
; M  \: ?1 j+ c2 `& Z* L7 R; ?
4.4 不使用浮点数
$ o" y: u7 P" R8 M; E  `内核不能完美的支持浮点操作,使用浮点数时,需要人工保存和恢复浮点寄存器及其他一些繁琐的操作。
2 G3 I, m5 s3 s2 q- U. B* v* [# j6 Q/ O$ D  n/ p- f' Z
4.5 内核栈容积小且固定1 D5 y$ R, R# Q8 }
内核栈的大小有编译内核时决定的,对于不用的体系结构,内核栈的大小虽然不一样,但都是固定的。
: S: k: A# V* i3 r
1 S0 Y) M7 z/ E& V# O# Z: z: O查看内核栈大小的方法:
! p, R3 _3 E& o" E( ~; d. J. G; d+ @+ g
ulimit -a | grep "stack size"
# b/ r% @( ?3 a: @" v  R+ X$ F+ K: J4.6 同步和并发& X$ h% L$ j, ?1 [
Linux是多用户的操作系统,所以必须处理好同步和并发操作,防止因竞争而出现死锁。
% O- v4 f! `8 U7 |$ q. x) f6 u0 l* E: V2 N
4.7 可移植性+ t2 s+ V* T! J6 O% H
Linux内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。

该用户从未签到

2#
发表于 2020-9-24 16:05 | 只看该作者
Linux内核设计与实现之内核开发的准备
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-24 20:50 , Processed in 0.156250 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表