|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
% v8 I; Z# s& K总结linux内核开发的coding style, 便于以后写代码时参考.( }& B) W6 H1 [! N2 t
6 y v+ V) e* Q& E; q下面只是罗列一些规则, 具体说明可以参考: 内核源码(Documentation/CodingStyle): A, i! m. I2 q9 G
6 K/ T) h, `! N4 V1 N' M: P9 q
7 v7 u% J5 o0 E/ q. M/ ^# _
5 K4 X0 F$ E5 ^" k" Q! @01 - 缩进
* x- Y3 M5 v9 ]7 t8 t缩进用 Tab, 并且Tab的宽度为8个字符
( t6 ?0 M. w6 J8 x2 g* z+ c5 Jswich 和 case对齐, 不用缩进
6 I2 A ]8 _. [5 y复制代码
' |$ R3 R: e( g6 Fswitch (suffix) {
& h3 U$ [4 l! M1 Wcase 'G':9 r0 _* A m- ?, F
case 'g':6 f8 c, K4 @. r/ K/ f
mem <<= 30;" q. Z7 y$ \5 E @* @9 F- n* X! a
break;
# x- s, k5 f: L! [! V& Tcase 'M':+ e# C5 M Y) ]& i! f2 k$ e
case 'm':/ Y9 d, \6 \' l3 \2 V) A
mem <<= 20;
' Q5 T( m+ A1 ?- j7 M. J7 ^& Y9 V break;
+ F! C- U, G1 S$ H$ ^case 'K':# r( J M, I+ D% I: j
case 'k':
$ [" j$ a% ^: A9 v+ L& ^) X# b mem <<= 10;
4 Y7 n8 K' _5 {+ j5 Y% Z /* fall through */
. O' H7 D0 c4 A1 y% l9 C) G* `7 d; Wdefault:# L: H$ x' V3 v; z
break;
: A5 A4 ` ?" s% o, i; ?5 B6 v7 w}
5 d+ ?9 Y" ~, [ f# E0 ?5 I" Q复制代码
/ b) r6 i. ~& T6 ^0 o* d% s' ^ 8 B# r8 v h; w- `0 v
/ K* r) Q7 e$ d* y a# R- B一行只有一个表达式2 B* ?0 O, ?$ A/ u5 R& @
if (condition) do_this; /* bad example */- t$ X/ A/ a+ x- d4 b* X7 g9 u! f
( j, Z; Y) Q% U* X
! [0 b1 K' @9 i
不要用空格来缩进 (除了注释或文档)# V* r f9 X2 w; Z* N
: U3 L: R/ r6 P
5 `1 l* t: v9 S7 i9 A6 ]02 - 代码行长度控制在80个字符以内! T8 h3 W! D/ n h: o; a M
长度过长的行截断时, 注意保持易读性
- u3 A+ C7 D) U* G' X- Y
3 Z# u- M9 g! K0 `0 I复制代码
. {; f1 w i' [- h2 }# |void fun(int a, int b, int c)
( Q. o3 t' n8 l; z/ ]5 y7 x" D7 B{3 _8 Z4 f' U( N- O7 N. X' `* X
if (condition)
: p3 k- p; V6 E' [ printk(KERN_WARNING "Warning this is a long printk with "
6 x" R- s# D2 ^9 t7 I" C# p "3 parameters a: %u b: %u "7 A' H! \2 ?5 T3 `* o
"c: %u \n", a, b, c);. c# M' s. z- _( V7 X9 ^
else
" L2 M! F, y X/ W next_statement;; K# Q6 U6 u3 c
}4 `5 Q$ {+ R, y# L' T, G
复制代码& ~& q6 n# {6 S
9 t4 m& T+ j( Y( R8 m( v0 Z; P
/ m: u( f# k5 m( ?9 ~1 F; W0 y
03 - 括号和空格的位置6 L, a- ~ m* _8 l& Y/ y
函数的大括号另起一行
% V& k8 k; { V$ y' Eint function(int x)
( P+ E" ]9 P# ?/ {+ n{ /* 这个大括号 { 另起了一行 */
. L: p" s$ c" N$ _1 X body of function, O2 N% g) f: A6 u+ I7 y1 F5 C
}. H/ I' E) s6 T6 S8 B. N" y
- ]& U* m. {1 ~- k" v1 X* s
9 F) h2 H/ f; F非函数的语句块(if, switch, for, while, do)不用另起一行
/ s& y3 ~/ P/ ^3 H! ~% M) Qif (x is true) { /* 这个大括号 { 不用另起一行 */
B8 O y7 ?* \' X9 \9 } we do y
& ~) K% ]. ~" \0 N9 K; E}
, T& H- E5 B8 x! f/ ^4 o! i: T6 U
3 K1 l8 }: l" k Q. c2 x+ o- o/ o- x; U0 K
只有一行的语句块不用大括号* |; K$ N9 x, \
if (condition)7 X+ b% u6 q* |1 X, J9 n
action();9 [3 q% z) O) H
" b. Y9 c$ Z/ v/ i7 i, x& H* v& i& l: o. l; w \
如果if用了大括号, 那么else即使只有一行也要用大括号' V+ V: i5 v- A7 @1 d
if (condition) {( a4 F: K$ s @+ F
do_this();
/ K0 f0 _$ {4 T$ Z do_that();% o; D8 S* h2 z5 I" b, ^& \
} else {/ d5 B7 ^" P: I2 Y
otherwise();
! e* L' j5 T: f" A1 Z5 ~}
: K7 A& V% J+ {9 t
2 u4 `# Z. D' q/ E: m6 ~
/ C5 m8 ^' }9 j t* A: l$ W' q, o! j6 M下列 keywords 后面追加一个空格
' |6 x7 Q2 ~; D* d9 nif, switch, case, for, do, while' P6 m% Y: o7 A
: g# a2 C2 k* q+ A+ y7 r4 X
6 A) I5 Q# A. B/ f9 B- ]2 \2 M- ?$ o' u x9 h4 }9 }3 ~' S
下列 keywords 后面 *不要* 追加一个空格
, H( O/ v6 w9 Q7 n, k' I' Esizeof, typeof, alignof, __attribute
. P0 P1 G ~7 z8 J. V5 t
2 |7 X7 b7 a) l6 n' ^s = sizeof(struct file); /* good */7 H; y( T, P. q
s = sizeof( struct file ); /* bad */- Y, l( L c- ^3 ^1 t
' p! m# ~: K$ _# M" `; S- {# z9 L+ }9 z& u: c# j4 V3 V/ I
定义指针时, * 紧靠函数名或者变量名
K* i" I( H# U' o* }char *linux_banner;7 `4 B" f$ ~3 P z$ C: q
unsigned long long memparse(char *ptr, char **retptr);; ^5 ?6 W7 A$ }5 q
char *match_strdup(substring_t *s);% J0 Y: f' {) P- S4 g& ^
- p8 X# w6 ?. ?
_* ~2 S" x% K% H3 [
下面的二元和三元操作符左右要留一个空格
$ l/ o& s; ?2 P1 s' q3 |= + - < > * / % | & ^ <= >= == != ? :! Z9 B3 J% O0 T; X( ]5 T6 I
+ t3 A% H2 U0 R 2 g d+ R5 B1 {- f
; q. Q8 X: H5 }$ S3 q! y下面的一元操作符后面 *不要* 留空格, {; n0 j1 x9 z9 B: ?$ b7 s, t
& * + - ~ ! sizeof typeof alignof __attribute__ defined
( {. V. r# [: Z3 n( c1 C9 V% D- ^( o, k! ^( H2 l
- W; k4 ?, Q/ Y; S# z2 w" l7 {
6 T- {5 W1 v7 E( G/ [7 w
后缀操作符(++ --)前面不要留空格
& D6 q2 @( N8 O # x1 R0 a1 ^9 s( A& C
9 a+ Z! k* {; s3 s* h前缀操作符(++ --)后面不要留空格
4 ^9 [( j1 l. j* `
! `; {. ^+ M- H. F( i% C
4 d7 w: K* d9 }. j# p5 m$ a结构体成员操作符(. ->)前后都不要留空格) T9 t" x% V, ]
2 F5 B+ [7 C; w2 l. S0 c3 ?3 o" q0 }8 i- n2 T
每行代码之后不要有多余的空格3 g: J2 e+ Z1 n3 @ {7 L2 I
2 I, _: }- d+ r# r/ C2 ^
- g4 T7 m$ z& F
04 - 命名9 C3 L. ]- W f- A/ S" z
全局变量或函数(在确实需要时才使用)要有个描述性的名称1 \4 U- i7 {6 U# |8 V7 `; q+ f
count_active_users() /* good */
# ~: M8 j- M; s8 b3 n' _6 K8 Wcntusr() /* cnt */
" m) @+ g' J/ i g. @! a $ t, Y# L8 j* U; ?- t* C
3 g: ]+ \( c& x' ~局部变量名称要简洁(这个规则比较抽象, 只能多看看内核代码中其他人的命名方式)% z- C* B) d7 }) y) h8 D+ R
9 {; D: ^, B6 q$ q& O% t. C# d' J# [7 T5 Q: D
05 – Typedefs; R- q* l8 ^/ f) E y: t! n
尽量不要使用 typedef, 使用typedef主要为了下面的用途:: r- D5 p, p. B% C' c) |4 X. i
) H& i) h6 a" q& c. c. r1. 完全不透明的类型(访问这些类型也需要对应的访问函数)
; x! S) }6 C( V& r- u: r# ]1 ^! S2 \% j+ c
ex. pid_t, uid_t, pte_t ... 等等
6 r0 ? g9 H+ X$ p7 R" Z! I f! ~5 {
2. 避免整型数据的困扰
2 n3 ~# G. V& e$ I
- D. H" @' ~- _$ ]) F& l. J 比如int, long类型的长度在不同体系结构中不一致等等, 使用 u8/u16/u32 来代替整型定义% Q) p$ M w, [$ E8 k
% ~5 n9 ?0 V% S8 z
3. 当使用kernel的sparse工具做变量类型检查时, 可以typedef一个类型.4 C9 g. H" o# z( f, `9 S, |
/ m. D8 {; c ^/ G4. 定义C99标准中的新类型
, P T- h/ r: B& H. [9 a: r7 N* {1 q2 ?% a
5. 为了用户空间的类型安全, z+ b& i5 j0 W# ^. R" q
8 w V1 I) \) r1 F ~+ |
内核空间的结构体映射到用户空间时使用typedef, 这样即使内核空间的数据结构有变化, 用户空间也能正常运行
1 i( i; m" B# [* R" r Q8 k" f Y; r, n1 z, ~/ k" {3 Y# K3 ^( i+ r0 ~$ I
' `& p% x' f( `3 D0 M4 ]& q
. G5 s) A ?: {& K4 l# o06 - 函数* p2 o6 y& I; f% V" _
函数要简短,一个函数只做一件事情
/ [+ n0 ]$ p$ Y/ U& B : r* P/ ~1 j! i; d; G- l
4 H+ W5 c! U @ L g+ ^
函数长度一般不超过2屏(1屏的大小是 80x24), 也就是48行* y: U& V: S9 @1 Z
: n+ l3 N& v8 z/ X( v' X2 e: k4 o- e1 T) p3 m! Y
如果函数中的 switch 有很多简单的 case语句, 那么超出2屏也可以1 v1 b' I( n9 k, d
- W$ U0 @7 o" ?/ z$ O
8 g: k( ~2 Z* L o% ^* Q# F7 x6 A
函数中局部变量不能超过 5~10 个7 R- ^; i+ ~! c, [$ X; j7 {
& `* @6 O$ v9 Q6 t
. C# \; p; E1 _6 Y/ E, \, C6 @函数与函数之间空一行, 但是和EXPORT* 之间不用空
0 E8 }4 m" T3 {7 h8 P复制代码5 E! [3 {! W. d7 \8 L9 P
int one_func(void)" L9 d+ O% a6 I" n" K" l3 B. A
{
. z) r! _- J0 ]) Y. n7 h return 0;' l, }1 R! }" Q, V8 p7 G
}
- r" H) r% d ]' l }$ v8 R9 Z/ u/ ^5 i
int system_is_up(void), y7 K* y* m& I6 w, \
{1 D" \3 w$ p. r
return system_state == SYSTEM_RUNNING;0 h3 ]" \9 i* Y
}, Z3 ~( y# n. S1 n
EXPORT_SYMBOL(system_is_up);. B) b& O2 }6 j3 b0 r
复制代码
+ W# F( |7 ^0 H7 P
, l- O5 Q, b6 @5 Q4 ~! f. r
6 b8 f# o$ c& C0 u* P: T$ K1 N07 - 函数退出
! l' c1 C$ F6 T$ U" \将函数的退出集中在一起, 特别有需要清理内存的时候.(goto 并不是洪水猛兽, 有时也很有用)) |; h! \6 {/ {) ^+ Y. w6 j3 i$ S
* K7 C' _3 z M6 f6 x( W6 H
复制代码
6 ] R3 ?* E3 e h7 ]& Vint fun(int a)# j2 e1 ~+ m+ J; y, ^
{5 g* P1 h5 Z. U
int result = 0;# u8 D2 ~* Q3 n6 r b1 W+ n
char *buffer = kmalloc(SIZE);
: W- Z$ o1 n& k+ X7 M/ P& K
. Q2 \1 c( N: I6 _$ R5 i! G5 r if (buffer == NULL)# W# ^7 G3 w1 |, h% k1 ? w+ k4 F
return -ENOMEM;' t$ G- u1 f; j7 d
! U' [/ I* I0 @' o4 z4 o$ o3 [% B
if (condition1) {( e' c# I/ i0 P5 u) T* ~
while (loop1) {7 i. @& ?; n5 N# J
...
3 X$ J) R$ q! p* ? }0 z) B4 [$ v) U7 ~5 x( F
result = 1;
" O( Q* ?/ \( j% b* I6 G+ | goto out;' i3 ^( Z; l/ D" e! u
}$ w: @; U+ D. Y7 ^6 D+ f' P
...( @: R6 A. ]6 L. {2 U
out:8 q4 T/ }; {# p- m( H
kfree(buffer);
7 O& C2 f0 y- U( y return result;
; }3 c* D) a* ?/ l6 D6 U}
?* B4 G6 C4 Q1 k$ r2 `0 K复制代码
/ Q. z7 @- Z& D1 \9 c
6 q2 S" u! \$ F0 _8 @& n' `0 r# U- m% e
08 - 注释
* h/ ~4 @3 O5 G h注释code做了什么, 而不是如何做的
# \/ M9 {) J1 N7 `: m, F ' k j% a# H1 e& i; T
7 [$ ]1 O- V: v3 k7 N: C
使用C89的注释风格(/* ... */), 不要用C99的注释风格(// ...)
# H @' y* t+ o4 C' u0 X1 L0 s- j+ w ' m/ X D+ e; \9 N$ G8 b
! K% o0 u- A. j, Z" w$ \7 `注释定义的数据, 不管是基本类型还是衍生的类型9 k. @" b+ ] b/ `6 [
% U; m ?/ ?* i2 `5 k! h1 ], z, `9 S3 y
09 - 控制缩进的方法
1 v$ T, T" Y* Z" }用emacs来保证缩进, .emacs中的配置如下:
( \! a8 z, d& n复制代码
, ^4 W' W& z! m/ b4 s' Y(defun c-lineup-arglist-tabs-only (ignored)0 c7 _- Q1 A9 `2 \. i3 y. {
"Line up argument lists by tabs, not spaces"
* i5 {8 a+ {8 h9 s9 J/ Q2 _ (let* ((anchor (c-langelem-pos c-syntactic-element))
$ m' V" L! d' D1 Y: G3 m- f (column (c-langelem-2nd-pos c-syntactic-element))
0 c4 P* P# O# G' i. q7 F7 j (offset (- (1+ column) anchor))
9 @* B$ y* w" Z7 ` (steps (floor offset c-basic-offset)))4 h0 y2 }; K+ j: h% Q7 D/ _/ t U
(* (max steps 1)4 P$ z5 y) X* l9 ?% o8 t
c-basic-offset)))7 T/ x4 p0 R4 ]8 L& p
1 X% }/ C( m3 m1 c$ O' T; a: b(add-hook 'c-mode-common-hook
. Q+ j5 l% C/ e5 w (lambda ()
% R0 w8 K% b+ t% _( z6 W+ ]5 Q. [ ;; Add kernel style
( L1 G; J' A! x- ~ (c-add-style
$ d7 j5 E5 }7 j "linux-tabs-only"/ [" t9 q% U+ L' Q. w* a5 J. ~8 y
'("linux" (c-offsets-alist9 M) Y3 L5 `5 U% Y4 V/ \* T
(arglist-cont-nonempty
% I& I9 D& V* H0 q% N0 R c-lineup-gcc-asm-reg w8 Q1 v8 o& O1 d: b) s
c-lineup-arglist-tabs-only))))))2 V" s; d2 p' y' O
8 |4 F9 I0 S' t& [. S L% O(add-hook 'c-mode-hook- F/ `7 c l6 O! h8 Q: f
(lambda ()
; ^5 [ y: Z' p$ T (let ((filename (buffer-file-name)))$ v5 u _7 h0 _( V1 q
;; Enable kernel mode for the appropriate files
) a( D0 O, f( @9 \ F6 g/ C" _' X (when (and filename: Z" M5 [; ~4 g- q" I6 e
(string-match (expand-file-name "~/src/linux-trees")
7 ^ ]) \8 c. p; C filename))
v, l# g: z8 B5 k (setq indent-tabs-mode t)) ^9 w" M, x) W1 \/ S
(c-set-style "linux-tabs-only")))))
0 I/ I+ u) }) N; D( a1 U/ K复制代码" I1 V, G8 L3 W# n% t3 P
4 }. b% ]" f. B& [' {9 h/ l2 f) ?' c) B' l2 H, o/ S
使用 indent 脚本来保证缩进. (脚本位置: scripts/Lindent)* P3 b( D9 @$ a& n d
2 C: v a# d$ w8 O9 y( F$ ]9 Q/ p& j: u2 V9 ]9 I# K
10 - Kconfig配置文件0 t) |! L3 N& b; E2 \2 G
"config" 下一行要缩进一个Tab, "help" 下则缩进2个空格' r; d: N, {5 B1 d4 [8 n. ]9 b
复制代码
+ Y1 E( ^! v4 B4 Dconfig AUDIT2 I% Q7 D) ?0 q9 m, v; K
bool "Auditing support"
2 O8 ~2 @! E) Y6 x- {- Z+ X; } depends on NET
' V$ N# x: x# A8 h, Y2 I; u& x help
0 U$ K+ U- W* Z& ~; |$ x! s, [ Enable auditing infrastructure that can be used with another; s7 \( D- r. V) y3 J0 _ r0 {( \
kernel subsystem, such as SELinux (which requires this for
# h7 ?0 }9 ]- X* [1 L/ a logging of avc messages output). Does not do system-call' c6 x' ~$ q3 [, Y" I
auditing without CONFIG_AUDITSYSCALL.5 [; x7 r: y# a. B% V' a
复制代码
* w+ `- ?+ F8 _6 d
: q( }- f1 H3 U J. d: B! g( G
2 K+ ]. W& p4 W- j9 E! U- ^8 ^不稳定的特性要加上 *EXPERIMENTAL*# c8 M7 Y q7 Z
config SLUB
! _: s! a8 I2 S8 [% @# U depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
# w* G# @, B$ h) a) b* h% w bool "SLUB (Unqueued Allocator)"
$ v3 g+ s2 z" J' J$ H& H .... i- t9 F, z, {
; P% Q" V* Z8 p& [6 T( p0 ?" [% l4 z. I+ N# I5 s* V% @: Y
危险的特性要加上 *DANGEROUS*2 A9 x: d; A w) r
config ADFS_FS_RW
, T6 I' J7 g+ a bool "ADFS write support (DANGEROUS)"1 M; r7 O, W0 [% t# z9 O8 f
depends on ADFS_FS
: m+ U9 p/ H4 a4 S' Y ...
: q* u) K; A+ D4 Z+ Q 7 _3 |& w: @/ }+ i# c @7 O
9 v ^& B. L. V" c) m2 ?Kconfig的说明可以参见: Documentation/kbuild/kconfig-language.txt) {; n% a) |7 T4 K# S1 N* K
* H( k' \0 c2 S1 e% [/ r
8 p3 U+ I) A4 f" y6 [( P. b$ r! P; m7 L
11 - 数据结构) p6 a6 d- N% ~0 z$ [" l
结构体要包含一个引用计数字段 (内核中没有自动垃圾收集, 需要手动释放内存)
5 b5 C) i0 Y$ k5 r $ N& X! S, {. i7 B" _6 j
, x) [3 Q, q% A, B# Z需要保证结构体数据一致性时要加锁
, U9 T" k5 ~6 l& Y
8 @6 c+ ^! ~7 a/ u4 p
5 G/ W y1 _' v1 M* z( B结构体中有时甚至会需要多层的引用计数
1 Z$ R7 a5 x% S1 z: Eex. struc mm_struct, struct super_block
$ d+ F& ^! V2 E3 s& u! Q8 ]
' J- d( v; Q, j7 U# u. V, ]
6 y1 m6 |6 y9 I0 U4 T5 t" E! q+ z+ R( J
12 - 宏, 枚举类型和RTL
8 r- s9 K/ x9 {* U% M宏定义常量后者标签时使用大写字母$ z" Y6 D, y. y& x
#define CONSTANT 0x12345
& h! K* I' i/ [9 G& i) q
, h: f9 b+ ]5 _: x& I; ]. U- ~
9 G0 I: M! \, g0 i1 G宏定义多行语句时要放入 do - while 中, 此时宏的名称用小写3 \, ^% }! ]- g+ W% M6 p& M; \! g
#define macrofun(a, b, c) \4 F) }( u& R9 |4 I$ J8 o0 n2 @
do { \+ h) U+ w% k \1 o% Z. ?
if (a == 5) \, Y& ]9 A9 S" `; l. @
do_this(b, c); \
" q- N# o/ D, Q* K+ j2 | } while (0)/ E4 P# _8 O* {; e+ r+ `
9 f+ X+ y7 c; ~9 | p# ^; u8 Y8 h d4 j' n
宏定义表达式时要放在 () 中
" p7 c1 i, d3 _6 ^#define CONSTANT 0x4000
/ D9 j' x$ G& j6 X#define CONSTEXP (CONSTANT | 3)% {' H5 X7 f' M( u7 a
) K5 O S# n- Q1 Q+ ]
! Z# ?! p% W& z3 z( Y H* \! y
枚举类型 用来定义多个有联系的常量; m; G+ J8 P1 R. k; J4 P3 G8 D
) } X4 E- ^# Z3 R+ `
2 E5 ?0 O: W5 Z) \# U2 ]! z2 i4 x% ?8 q13 - 打印内核消息
; L% X' G% y: u- N9 r& R7 D保持打印信息的简明清晰- e0 b2 v* C* l: j
比如, 不要用 "dont", 而是使用 "do not" 或者 "don't"# B1 v" n( U d6 S2 h2 \6 A
) v8 x( o6 I3 r5 _2 I
2 e6 K( ~, N4 y. |; Y4 H; _! ^: X E! A- h' \
内核信息不需要使用 "." 结尾
7 ~) H3 E: O5 N# f
4 P }, f& l0 f3 J9 K+ t- Q
$ ?8 F& H* k! J, f4 N打印 "(%d)" 之类的没有任何意义, 应该避免, b# h4 g. E9 j( K6 ~, v; R' O" l
d8 ^/ V" n6 ~9 ^/ m9 [5 q8 [2 i- s3 i
选择合适的打印级别(调试,还是警告,错误等等)
6 u6 `' ^* S& \6 S' ?4 v$ d 2 d0 T5 |- n4 L% O+ [
# L! H1 j& m9 W7 r( D
14 - 分配内存
' G; |* ]" P0 t- x分配内存时sizeof(指针) 而不是 sizeof(结构体)
8 G$ k: s: @$ Z3 [4 {p = kmalloc(sizeof(*p), ...);
2 A( E8 ^ s0 U1 j这样的话, 当p指向其他结构体时, 上面的代码仍然可用
& A0 y6 U( t* z& g/ R- Q
6 @) |- p! F' T1 h( V
2 N) Y, H4 C4 Y" x& d( ]" [& l# l
2 ], R/ h) t; r K: W* w分配内存后返回值转为 void指针是多余的, C语言本身会完成这个步骤- X/ m% l8 N5 U# r- a0 F
2 T) j- E' s2 ^ [( V: U
. B, \1 g T4 _$ N15 - 内联的弊端
( L$ Z4 B B( C7 f9 @. y7 G如果一个函数有3行以上, 不要使用 inline 来标记它4 d3 V4 o# {3 S* ^/ K' E/ A
( r1 W) I7 s& g' j9 G! F
1 |$ {! @+ a' N1 M
* G9 s' @: `0 U16 - 函数返回值和名称# S* L Y5 T6 x# R g1 P
如果函数功能是一个动作或者一个命令时, 返回 int型的 error-code. N) W, S) K5 o) l6 z' M1 s
比如, add_work() 函数执行成功时返回 0, 失败时返回对应的error-code(ex. -EBUSY)
" y" ^4 p K, q# P% f! b4 X5 p& l( i' O
( k: _5 ^" i/ {2 ~$ y0 F9 E# R I2 w$ O/ x
如果函数功能是一个判断时, 返回 "0" 表示失败, "1" 表示成功0 S/ m! W8 N! _; s9 N
r! d4 }2 y% B
8 \" k" O9 p9 u! [所有Exported函数, 公用的函数都要上述2条要求
# Y& C0 l8 ~8 R) |- S ' v# |& L K! W6 x- [
4 F: Q3 i, L4 p6 H; Q
所有私有(static)函数, 不强制要求, 但最好能满足上面2条要求
6 e' }1 F( u# \0 z3 q0 q- Q ) r+ p; m( ~+ ?* D
5 ^2 X- o& P/ j. E
如果函数返回真实计算结果, 而不是是否成功时, 通过返回计算结果范围外的值来表示失败
2 X' H" T1 v/ y$ V! G: }" N; {比如一个返回指针的函数, 通过返回 NULL 来表示失败
' d+ d; Y# b: w! Z1 v- Y* O4 {6 n" Z# V3 G
?% b6 I4 D9 n, j6 \) G/ Z
. ~ e3 w* I) F f
17 - 不要重复发明内核宏
7 w W, B- F4 Q: r内核定义的宏在头文件 include/linux/kernel.h 中, 想定义新的宏时, 首先看看其中是否已有类似的宏可用, ~- q3 x" g4 {! t+ A
U! |8 ^. s4 c+ Z
2 q; E# W' c( e7 u! c- i( P3 ]) M {8 j% A/ T' a
18 - 编辑器模式行和其他
3 p/ _2 \& b. _( `+ x不要在代码中加入特定编辑器的内容或者其他工具的配置,
( i0 e3 N; t: ^0 [
4 |2 @ i' H n8 W o3 M比如 emacs 的配置
4 \; |, ]5 v- S5 ?! {5 I0 _) u4 D, D2 a1 V2 [- j4 u. i
复制代码, ?& F. o* x$ t l+ J
-*- mode: c -*-! Q* i4 f" _. k4 V5 q- ]; [: E! U
or6 B" Y6 |! A6 C+ y9 B7 n2 c; ?
/*
9 ?! j4 [: h1 v2 t3 q- _Local Variables:
0 W' \8 L9 s4 R9 e" r) U1 ucompile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"2 G5 l! \* D1 N) Q9 ~6 U4 X
End:* O6 F n1 T8 K& C1 m
*/. i4 t7 s0 W$ z J) N5 n
复制代码
- Z* O; u. @9 _2 ^0 m
' W+ M' _ `9 W" {: o, B
9 B9 P! U* H( n# Svim 的配置
, G1 X( v- `( L( V
0 ~1 n K5 d+ F+ W/* vim:set sw=8 noet *// S7 `6 F8 ?6 } k" ~, R
8 T( R7 T, ]. w1 f
* m1 q! S% D6 B+ D- E每个人使用的开发工具可能都不一样, 这样的配置对有些人来说就是垃圾" x) a. e5 _2 W9 N9 n
# L3 I& e8 d/ H4 i
; C- y. H5 n' G7 y7 G3 L4 o/ s
" c9 D$ `/ j, [$ Z8 f" B% f9 ^: a内核代码格式化工具介绍$ }3 B: |. G6 S+ ^$ i
checkpatch.pl - 检查source或者patch是否符合规范
e- C3 r' {9 M- O6 l$ ?# bLindent - 格式化代码的缩进
- x, Z% \- k2 r+ U; U0 q7 N4 ~5 O $ t# b: u6 }! v R3 v4 z
+ `( ]' R( Q g这2个工具都在内核代码树中的 scripts 文件夹中。 |
|