|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
L3 q- ?' w0 ^/ ?" o3 E总结linux内核开发的coding style, 便于以后写代码时参考.
& Y W- \5 q5 u, o- s0 W
4 [ V3 k0 A& q7 K# U8 \0 y6 P下面只是罗列一些规则, 具体说明可以参考: 内核源码(Documentation/CodingStyle)
$ X/ L; Z- }# [% W2 j
" ]: E. U9 U' p# f: u6 G9 f ; e% @6 ]. \: R9 _. @
/ |) f. }6 v* ]
01 - 缩进
7 ^4 W, C0 R0 u缩进用 Tab, 并且Tab的宽度为8个字符
( ~3 `6 {% m7 N' b( z% Qswich 和 case对齐, 不用缩进
: p; O* Z! p5 @0 x% \复制代码
! z) r7 H2 k# |- x$ x8 cswitch (suffix) {
( c, S. V8 Z1 o! u8 Pcase 'G':! j) v( w* s+ M* \
case 'g': M+ C( P+ o) l! `0 g6 X
mem <<= 30; _ _0 y o& ~0 m! w
break;
. g2 \4 b% w, s6 v. f3 _: C: Lcase 'M':
0 ]/ @9 O1 n) F4 [4 P6 t& Hcase 'm':, ]' Y2 A" S5 m5 \9 k% W: G R
mem <<= 20;, l% w7 l7 ?6 E
break;5 C9 Q. L' A: ^" E/ o
case 'K':
) U, J4 o/ R% A8 D( p1 f! M7 {2 bcase 'k':5 X, j- R( x/ _/ O) v2 U
mem <<= 10;
3 x* g( X' y: q- G! H- [ p /* fall through *// c/ `7 J% O8 b- ~$ g5 z- K
default:
: R" f J1 G! e; K, b# y break;9 h1 s5 m4 t: U/ }, y0 }8 F, ^
}" P/ v& e) c# ]/ k; _% ~
复制代码
: W1 L/ ~1 j& }7 [) d# H( y, t
( `4 \- i/ g8 O; a9 x# |9 x: B' Z' n# e# z" q$ b% D( }
一行只有一个表达式% l, y, j* [6 w! J% @, \; y( L
if (condition) do_this; /* bad example */; N4 O( n3 @- ?' `0 X
0 I2 n: H. I9 D# P3 i4 ~6 c) `% a5 r2 B% J4 r9 g
不要用空格来缩进 (除了注释或文档)
; }) f( U- o) M
# E2 f! p8 s3 M& W8 e" u4 I2 A
/ p1 _' o) |/ o' F1 n+ P02 - 代码行长度控制在80个字符以内
# ]# {. G& K: U0 z& w长度过长的行截断时, 注意保持易读性- O1 J" |( a9 {2 X* o5 J
; W, E3 O0 J% a- a! B
复制代码' o3 k- I/ R5 c& K q
void fun(int a, int b, int c)' G+ M1 M- K* F, S
{
4 V9 h6 L/ }' a, E, p if (condition)# ~( d) C2 d6 B9 N2 q
printk(KERN_WARNING "Warning this is a long printk with "
! ~# ^! g. N1 D' d* ^0 X$ a "3 parameters a: %u b: %u ". q6 |) l0 N& R6 a1 ~$ i4 Q/ J
"c: %u \n", a, b, c);
' [& {2 G2 ]2 z: ^/ ~ else3 Y1 Q" L, I) }
next_statement;. u9 J$ U; R u4 S% ]
}( ^' x; y" Z& ] |
复制代码# U o& E6 x) a: H6 j( n0 I6 @7 g
' j d& P" |& G. x/ r* e% q
E$ z) X8 t& ?5 f7 p03 - 括号和空格的位置
( I3 n( s1 c) s# N( X T函数的大括号另起一行& h' P/ X8 p# T. @- X% Y& ] }5 q
int function(int x)0 \% q7 P7 a' z' v5 r2 L& I; d
{ /* 这个大括号 { 另起了一行 */
- e4 T: f! O7 G+ N2 I: j; S body of function+ y0 f" r: L+ H* f: b( u3 m" H* x
}9 O& V( C# [1 B" ^; r6 o$ i+ B, X
/ V$ K1 g2 Z' @
* o' E) g0 v4 O. S8 D: W& g, |" _+ m非函数的语句块(if, switch, for, while, do)不用另起一行. V8 v( u5 _( D% N+ n6 i
if (x is true) { /* 这个大括号 { 不用另起一行 */, q* L* p7 L2 W$ {
we do y, g( w6 {- \* r, l/ U
}- W2 U4 h7 p' I4 V# o
& Q9 |& L" j; n2 @% ~. N9 n' b
只有一行的语句块不用大括号
; E3 W, r1 t0 @: ^if (condition)
% T2 [5 @1 C- b" P" {+ Y9 @ action();
& f& `% ~2 `% f$ S D1 z 5 k" M F! ]% O7 V1 L
1 [" h) Q* p' O5 @& e
如果if用了大括号, 那么else即使只有一行也要用大括号; x. j; `' B& f9 j n
if (condition) {: h# o* g, Z) T
do_this(); Z8 y+ d2 n$ p' M. `! U' C+ q! K
do_that();! {" a3 R3 x' O
} else {5 _0 m: s7 y! m& z( ]2 [* }: _
otherwise();5 o) ^8 r3 O, t1 W& j7 p9 J6 U
}
& j U+ j/ W) J0 ?( w8 ]
! j; Q$ i: d- w. G" \! n! J
. K+ r' q; a* t& |0 ]9 P下列 keywords 后面追加一个空格# M$ |- E+ k4 o: S; f/ T
if, switch, case, for, do, while
, z0 ?+ F' {$ t$ {1 s2 E
; n# c! @! r2 Y2 V _7 y
' v' W, g% J( a6 }
& S B) D" o+ x下列 keywords 后面 *不要* 追加一个空格5 ^% ?1 y I4 S! f3 z
sizeof, typeof, alignof, __attribute) O8 _0 s8 D. j. w- w& y
# {& [& T5 M3 us = sizeof(struct file); /* good */
, e# N3 G% y$ v) c# s0 B0 `5 d! ps = sizeof( struct file ); /* bad */
4 ?% j% j( r9 J1 j& F, o% f7 V4 T
- r* w6 Y6 N% r2 Z3 \
, {! F+ t8 }' c定义指针时, * 紧靠函数名或者变量名
- @2 ~" w! H6 k* y. {char *linux_banner;
. L/ V1 o. P; i: a! G6 junsigned long long memparse(char *ptr, char **retptr);
, M) C) A" g: m3 t0 h' \char *match_strdup(substring_t *s);; w! p1 T& a: h1 R, H: Y
C- r f, }. q/ l/ p( u
; |1 H& h! }& Y& n# w% `" g0 r$ E( v
下面的二元和三元操作符左右要留一个空格
+ @$ u3 e2 d) |; ]% O/ t= + - < > * / % | & ^ <= >= == != ? :
, w8 b( T0 S/ K W% r1 D( X) M( P1 j8 b1 C T1 C3 C9 H4 O. ]
3 q" e+ ]+ x N% [3 P
0 K# a0 n/ d' O7 d4 w. V3 Q$ _下面的一元操作符后面 *不要* 留空格
) l7 \! a) ^% W; W+ l; G& * + - ~ ! sizeof typeof alignof __attribute__ defined! S8 `% j' S7 x3 n& J/ z
* {6 ?$ a9 O0 n4 p! G$ @% b 1 r/ b/ C& L9 i! Y( i) ]" Y/ i! P
$ {; R) B& m" J5 Y* Y后缀操作符(++ --)前面不要留空格
% n2 ^, |2 Z2 X( }6 e( X
2 d5 e) r) n' \! ]& e/ {
4 f3 d* ]5 u# f$ a6 B. h前缀操作符(++ --)后面不要留空格4 Z5 g( K/ \8 I5 j8 P5 Y# B
. h; E1 g! `. V* D( Z
" S4 [7 b7 Q9 V, I' q. w* U结构体成员操作符(. ->)前后都不要留空格
; t; e# ]" ^: B1 w & j V0 w( ]6 o3 V, f
7 K- P4 m5 u% n3 ?+ y% g, K9 H每行代码之后不要有多余的空格
3 O0 u$ f( Z c u( v " @0 v! c5 N# h9 M8 \
, D. b& }: h/ l7 r; J9 N" J
04 - 命名
2 u% ]1 D; j* W1 T5 T全局变量或函数(在确实需要时才使用)要有个描述性的名称
! S; M/ C" L, T' e$ [. t% e1 R9 C( Jcount_active_users() /* good */
) |: {. r1 z8 C( g7 kcntusr() /* cnt */
+ S4 Q& S9 l9 a ; |8 ?0 o! ^1 j! K* }; z6 R @# G: `; M
f- d3 J6 H" _6 A% Y
局部变量名称要简洁(这个规则比较抽象, 只能多看看内核代码中其他人的命名方式)6 r: E; ?7 I* a, A2 N. Q/ O
1 M1 Q' S8 p6 Z! K! ]" F# X- N0 o! |
. h" P+ e, T) b) t# h
05 – Typedefs2 n; ~& s9 w; T) u) O4 M$ D
尽量不要使用 typedef, 使用typedef主要为了下面的用途:
& _, F P+ }& i% `4 R1 _2 I. U( K0 ?; Y4 C5 k! N5 R
1. 完全不透明的类型(访问这些类型也需要对应的访问函数)
/ E4 L! o% t* K7 V# V9 }9 H% B' j; B3 n' ~
ex. pid_t, uid_t, pte_t ... 等等
" h- ?1 u6 K7 y, E7 w7 G7 S5 i& \
2. 避免整型数据的困扰5 I# `. ?! v; e' T
' O' f2 W& a$ @7 o
比如int, long类型的长度在不同体系结构中不一致等等, 使用 u8/u16/u32 来代替整型定义3 ~. E) p# n& q, |3 x0 A8 O
( V+ D" c8 o& h) i6 b
3. 当使用kernel的sparse工具做变量类型检查时, 可以typedef一个类型.# B/ V! [ t/ [( V
; j" h4 ?% j- ]( @4. 定义C99标准中的新类型
: H+ N. v# u7 B2 x8 b, c6 j
) L: E, @+ u5 Y5. 为了用户空间的类型安全- O4 k( g% K8 L3 X( a. A7 Z2 F& H; n
7 G4 r/ _! b0 J2 L, ~0 i0 j
内核空间的结构体映射到用户空间时使用typedef, 这样即使内核空间的数据结构有变化, 用户空间也能正常运行
{% ?9 I1 g7 ~) o; f
7 a. H* I+ s3 ?5 Q2 N: [ 4 G/ X8 i' A8 h
# ^: Z% F1 H- x) @/ g; c06 - 函数: Z' ^' |+ q; s5 e- w) _
函数要简短,一个函数只做一件事情8 u; C% A+ [1 i* t2 j- P
; {: ~+ W, f7 w7 t2 [
3 F" ~# S+ L p+ n" v2 z
函数长度一般不超过2屏(1屏的大小是 80x24), 也就是48行
6 `% B) Z G- N3 W. A$ m" n
3 r/ L! z) X8 i2 u z# ^1 y
, R9 ~3 X# X% C; C如果函数中的 switch 有很多简单的 case语句, 那么超出2屏也可以6 f0 ]; u3 v0 m! ?0 ?
9 b. A. F% t2 D0 v/ ?
7 Y: s, L% B; I' C! G7 W函数中局部变量不能超过 5~10 个
6 p" g+ d5 V) F9 D/ W$ A 3 `; U1 j( r& k; i/ B9 K
1 z+ }; D% A# }' c# L& Y
函数与函数之间空一行, 但是和EXPORT* 之间不用空9 i" U$ z5 V& Y% @$ z' e7 m7 y1 @1 T
复制代码 p' \! i# w' e4 G2 [- R' [
int one_func(void)
" I, {- m0 h! Z! U1 A( T9 b6 ?{
* l9 w5 x$ |5 l( M return 0;
; M) d( q) o' X" H% U4 f}6 k* f! s! s) M) v
) \% J4 e* t, J- w6 M3 S! Dint system_is_up(void)4 a* M. y$ |3 Y) t/ B
{6 N% R- i: Z- Y% J: f. o5 r( y) o
return system_state == SYSTEM_RUNNING;8 Q4 ]0 r1 a) m, {5 ]
}; T. x( Q6 M H, a0 f, f s1 g
EXPORT_SYMBOL(system_is_up);0 r9 j' V) `% C$ u% W
复制代码1 n$ `& n3 q/ T: v0 o
4 h% A0 a3 T* D) S
( ?! y7 L5 }( f3 S3 Z
07 - 函数退出' u4 w( F$ w4 z
将函数的退出集中在一起, 特别有需要清理内存的时候.(goto 并不是洪水猛兽, 有时也很有用)
, o4 O. E' ]- [" X
% `# K( C. H" I. h, U# n, z* H复制代码
$ d: F4 q9 N* `5 g+ Kint fun(int a)
& s z5 P, X1 B5 ^% P; f9 a/ B{
' i2 V$ l: r% t: Y int result = 0;
9 ]2 Y( v" \) l8 b# h) @ char *buffer = kmalloc(SIZE);
" W+ r$ @, V9 A0 f$ R6 ] s7 \) \
2 v& w. Y4 W( @0 { if (buffer == NULL)
! `! d: b& w( j" {; W* _; g return -ENOMEM;
, C7 N# k& k' l' f8 e$ Q, W# K' l8 q. ]( }" @0 D" J9 D, z( w# H$ z
if (condition1) {
# p! ^7 ~. b) z% D; V G while (loop1) {, p9 X! ~( I7 ~5 r# e+ j5 Q
...5 R0 Z+ Z- v/ W
}
- l& L2 K: n R4 @ result = 1;7 U9 m9 K4 M3 A1 O. p
goto out;" u: ?0 n; C8 |7 ]
}+ y, [8 @; @2 ^/ M
...
7 ?- C# n( ]3 E# W out:2 k- y" }4 u& s7 `
kfree(buffer);; y4 H4 ^+ v) u2 x- j/ I
return result;
' e }; R/ x$ o7 _ V6 R+ n}+ y. k* t3 a q3 z7 ]
复制代码/ Q% E& e- {/ O
' k; f5 E; H, m& J& j9 y* O
& k6 S* I. T- h$ z( S/ ]4 P, ]
08 - 注释( H$ e) ]7 |6 j- H5 ?4 P6 X
注释code做了什么, 而不是如何做的
3 I- E( Q+ T B6 t( m$ c) f 0 z. v0 n. h6 C- S" ^
* ~ e2 U$ i; G3 x4 s# j4 i9 X使用C89的注释风格(/* ... */), 不要用C99的注释风格(// ...)8 V! F! W& m1 t% g' q
8 A- C' e1 j4 X7 x5 w
+ c: l9 N M/ v" M注释定义的数据, 不管是基本类型还是衍生的类型7 _4 l9 G6 }9 Q6 T
( ]: i0 u' y, S' {& U: b6 Q' w' v. X( U: U3 p3 A, E9 b; B" }
09 - 控制缩进的方法
9 f, c, W: n9 ]" G( Z: j2 t用emacs来保证缩进, .emacs中的配置如下:( m4 ~7 ]% Q7 F
复制代码, x! D; _) z X# q; E/ N
(defun c-lineup-arglist-tabs-only (ignored)
; N) l$ H( Y( s+ G0 U: t "Line up argument lists by tabs, not spaces"
3 R) c/ Z% u7 L! f (let* ((anchor (c-langelem-pos c-syntactic-element))
" r0 ^4 F3 ?: V7 e" E4 W k4 n# j (column (c-langelem-2nd-pos c-syntactic-element))
. t6 C7 q! N4 K7 }) @5 K (offset (- (1+ column) anchor))0 c" W* G2 |& w% \' M
(steps (floor offset c-basic-offset))) w) q8 z* r! N/ U2 |
(* (max steps 1)& b1 H: `' I. ~* T; c9 d
c-basic-offset)))8 i. i; Q# p: p* e# r3 X& O' l
|. b; m5 ]! A- b
(add-hook 'c-mode-common-hook! p1 D, v2 z& G, l5 o6 B
(lambda ()+ l0 O: K" t' R0 D: {# T/ I
;; Add kernel style# h' Z* d) k8 }/ F4 @- Y
(c-add-style9 w7 `4 X/ W; V9 j
"linux-tabs-only"$ y( o1 e3 U. C& ^' b8 m
'("linux" (c-offsets-alist) `; S# m- h( |# O+ P% h6 O
(arglist-cont-nonempty8 @# T, n5 a5 ?3 M) r5 ]2 X
c-lineup-gcc-asm-reg
# R) C0 X- S" X3 N/ {9 N; w c-lineup-arglist-tabs-only))))))1 u2 A: z+ p! Q- x4 i* x
' `( v# J# {4 O* W9 c4 s1 H5 d7 h
(add-hook 'c-mode-hook
1 {. p1 ^. [: @# M& v+ Y (lambda ()
- w. H7 l6 S. Z) f) V! E (let ((filename (buffer-file-name)))
- }. A: f6 c' i ;; Enable kernel mode for the appropriate files( C1 g9 H, O( ?* o8 L
(when (and filename
1 q. q8 \* _5 X& s (string-match (expand-file-name "~/src/linux-trees")
5 G0 ]& ?( k$ F filename))
% V, F [9 s! \% T; i) n (setq indent-tabs-mode t)
! I4 @1 s$ {- l$ X. n* ~3 T+ g( M) Y (c-set-style "linux-tabs-only")))))
& z8 i6 s0 ? ^! u7 I复制代码3 q6 q& _7 X' I6 f1 |0 Y! F: x
7 Y4 a4 o" @9 ?7 `, m* B9 {1 ]2 l
8 L2 e2 O3 l7 o, Z# B
使用 indent 脚本来保证缩进. (脚本位置: scripts/Lindent)6 H% Y5 z7 W* P
. A; M7 Y& S: M" W
, Q# T) {6 [2 _" C8 E+ T10 - Kconfig配置文件
7 h, n* ]+ w' E' Y0 B"config" 下一行要缩进一个Tab, "help" 下则缩进2个空格
% _0 i% {/ s; i. t复制代码; L9 _, j P/ o' O
config AUDIT; s6 v) ~9 F' R4 i5 |$ F3 S
bool "Auditing support"
$ Q& a+ X8 s% w/ b' g+ c+ \: d/ p; ]1 ] depends on NET. @. `7 q9 R1 J
help
) A1 j9 v! C' }2 M* X Enable auditing infrastructure that can be used with another
. ^+ E0 R- r+ Y) L' @* J kernel subsystem, such as SELinux (which requires this for) Q7 s9 Q8 J5 H. t0 r5 b, M
logging of avc messages output). Does not do system-call* k% r# S7 D' R: x; C K
auditing without CONFIG_AUDITSYSCALL.
9 i0 f; c- E2 E$ x/ P复制代码; l8 g0 b9 u2 t a
8 q4 E. h- C7 O0 K+ F2 a) X1 o* ]- N) L2 ^, p
不稳定的特性要加上 *EXPERIMENTAL*6 ]" o" n6 p+ V" a
config SLUB* h2 _; U/ X! T
depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT4 {6 ?9 K) |( F* }
bool "SLUB (Unqueued Allocator)"4 Q- a8 x7 B; Z: J* g+ ?4 o
...* ?& y$ A2 @2 `; C9 o; f+ _
; j6 p* e) V/ S2 M+ q0 X
( c1 e2 p, z; u危险的特性要加上 *DANGEROUS*9 ~) v; z! E, p2 F! G* U
config ADFS_FS_RW! j% V7 B/ b6 l- [; S! q1 b0 X/ h' c
bool "ADFS write support (DANGEROUS)"
0 C1 I" l* w# ?+ E; s depends on ADFS_FS
* N. k2 ^% U; J$ U9 Q6 p ...
) v3 a# R( R+ O 3 a; _4 h0 P# O; y% W2 @
, V4 _) |* [/ A$ O
Kconfig的说明可以参见: Documentation/kbuild/kconfig-language.txt+ s+ c9 G+ B9 V: s B# H
1 h5 q( j/ ?7 Z6 |
" y- q! _7 N' l" j- _- F3 L D. m% M( y4 a- d: z$ y* m
11 - 数据结构
" v/ P% l* {: Q& r! o结构体要包含一个引用计数字段 (内核中没有自动垃圾收集, 需要手动释放内存)/ ?* y$ X! p. ?( Z' L
" `. V+ l7 N3 j& s
1 l7 u: E$ P5 [/ g7 |- @需要保证结构体数据一致性时要加锁* m$ R2 M* a- x' ^
; |( u/ |$ u2 u+ Z0 \- x! K7 G! D0 K' Y1 D$ p4 X8 U& ]
结构体中有时甚至会需要多层的引用计数2 p; I, M) g I4 a3 e, r+ j: x! a( n
ex. struc mm_struct, struct super_block' r9 y& j6 S+ _- t3 v- Q/ n
2 G% C: S+ e; i: D+ w1 D
' X- \& E( [: A1 u6 K* I% [
9 |0 b0 i+ s6 g- R
12 - 宏, 枚举类型和RTL& v, s' S; C6 \) H% l
宏定义常量后者标签时使用大写字母
$ Q7 P; Y( l7 t1 i! i! v# @#define CONSTANT 0x12345
9 M Y! G v6 V3 Q3 L7 N ; z: n$ E8 d/ a5 C/ X( S- ?! p
1 \. ~, n: h i# |
宏定义多行语句时要放入 do - while 中, 此时宏的名称用小写
# ~2 H1 q! Q/ y3 i5 M#define macrofun(a, b, c) \( O8 B l! k. @. U0 }
do { \
8 m8 I( o5 O+ e4 s/ x6 ^# {! T if (a == 5) \
9 n# G% J: ~2 b- e* Y* a do_this(b, c); \
& [- w. z1 W3 @" s! B) y* a: ~) b, b } while (0)
6 `6 F8 _% _; b8 H, R( p4 f) z. S
c. X- W* B/ Q/ d3 h
5 k7 \2 y( F' O9 ~% \ H5 Y宏定义表达式时要放在 () 中9 I' K4 x+ ]0 c0 y, l
#define CONSTANT 0x40007 Q7 y: B. E. d6 s7 ?0 K* y
#define CONSTEXP (CONSTANT | 3)/ C/ W& |9 x! U1 O7 v( ^8 `
& H- S( `, u+ B0 y. X
- t6 [' @) O$ u1 V枚举类型 用来定义多个有联系的常量
2 x' h/ M6 a0 Q+ x ]% d% E 8 F$ h/ b4 R6 A; m* v/ }
- j4 i- A6 A. g( g: o: e) K
13 - 打印内核消息3 m% |! F! e4 T+ o: A3 |" t4 S
保持打印信息的简明清晰
# Q" W6 G4 f# Q& ^比如, 不要用 "dont", 而是使用 "do not" 或者 "don't"
* H6 h/ i, P) l. q" A& W: i. O9 Z3 A7 ^7 @# C9 D
9 N3 T# ^/ W) B6 P. `
0 l) x) P6 s8 c% z6 ~内核信息不需要使用 "." 结尾
+ O: m+ N4 n, X& g2 G ' N h) v. L" H& ~
9 V8 Y/ d6 z$ F2 _打印 "(%d)" 之类的没有任何意义, 应该避免4 H' d; b+ @9 o1 G, F
% R+ x. c# V% o4 G7 P
8 L; e6 M" @# I7 @* q7 |! K选择合适的打印级别(调试,还是警告,错误等等)4 f* s- L. t0 Q1 d! S r. y7 j
1 K1 p' P! b( O0 p( E% \
% O }/ G. W7 p2 C5 x14 - 分配内存
8 x; A: R. Q8 V" L S' z5 t4 c分配内存时sizeof(指针) 而不是 sizeof(结构体)" k. t) _) i6 l& e: w ^* E& |
p = kmalloc(sizeof(*p), ...);
, G- \# [; T2 k7 m" e9 K这样的话, 当p指向其他结构体时, 上面的代码仍然可用6 m9 a x9 O9 A
' Z$ H$ N4 A0 o0 d4 q 8 F* u" {- X9 h# r
; D& F& w8 M) f: `) c分配内存后返回值转为 void指针是多余的, C语言本身会完成这个步骤
' J- I/ ? W6 h+ N3 M+ P# b & l- I9 m+ a4 J/ G$ Z' ~
' a5 F$ H5 N- {! T% \ O3 y/ G2 N: L
15 - 内联的弊端5 b6 S& K+ E2 J9 \9 S+ _
如果一个函数有3行以上, 不要使用 inline 来标记它
6 r+ ]! g5 I: N" E& ~0 L$ m8 m$ n, X
( g9 h* `, N9 v5 g4 R* [0 i . D2 Q2 O& e" y& d
3 Q: ?8 p; H3 R1 {+ v9 x16 - 函数返回值和名称: I! c7 ^7 Y9 z# n$ }+ B
如果函数功能是一个动作或者一个命令时, 返回 int型的 error-code6 m7 t* p" X, ~
比如, add_work() 函数执行成功时返回 0, 失败时返回对应的error-code(ex. -EBUSY)
% T" {5 I$ p$ r5 {( L' | v# O# `. G% J4 L5 [$ v; N
; a) w2 y" f' ~
( w- i x. a- G, B0 b
如果函数功能是一个判断时, 返回 "0" 表示失败, "1" 表示成功4 l& }3 H4 I8 U& U! j8 {
$ n1 K* }1 R) i* P4 z5 N' w. Z4 r/ B1 X# \! K, }
所有Exported函数, 公用的函数都要上述2条要求
7 ?9 N+ a- c: k6 i g
# N1 Y, Y8 S: K
6 i4 o! E6 b3 Z7 H4 x+ }' w所有私有(static)函数, 不强制要求, 但最好能满足上面2条要求
& Y$ T8 t# p4 L' u; y% h9 F
% |8 ^% z" h1 n, E' O- ]
# G' ?6 h1 s& ]( z如果函数返回真实计算结果, 而不是是否成功时, 通过返回计算结果范围外的值来表示失败
2 N4 N+ A7 y5 M4 H+ d* g比如一个返回指针的函数, 通过返回 NULL 来表示失败8 W+ p$ O Z: D+ D
1 i4 ]- K$ R# V' I% k
( ^9 J0 a3 N5 z" i( N/ i4 G) N. T& y5 l( l7 n
17 - 不要重复发明内核宏
4 B/ |8 g4 ]: r5 ]内核定义的宏在头文件 include/linux/kernel.h 中, 想定义新的宏时, 首先看看其中是否已有类似的宏可用, F" s* l4 t- k% Q# N
9 S) l3 F. y' J8 w; p, n 8 J) n, i& y; {% D. v
& M0 j& n" g, }4 l+ B- e18 - 编辑器模式行和其他* \# N. T" U4 l+ d: n" L2 D
不要在代码中加入特定编辑器的内容或者其他工具的配置,
2 k7 h0 ~; a. h# x4 H! F, r H+ R) j: \
比如 emacs 的配置( C+ F7 \5 R t0 L
* Z! x7 o6 g* b% n% j& i
复制代码; r: K6 L5 g4 ~ l
-*- mode: c -*-, j1 Q# y# j9 u9 q& p" p
or
9 k+ b; w# N0 x4 D/*$ K3 `7 i/ q: R8 U+ _2 V: R8 [$ w
Local Variables:" _6 w; E) l# E0 a; H
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"9 e; I3 L+ ]8 g1 L& x& K
End:
% k" k( X. q. ~, e# R*/) z) f6 o# G& a8 [( r/ y
复制代码
% S5 v/ r, ~* x
+ v4 E' K+ @4 g+ r9 n4 E$ J
; v% T4 w. V4 cvim 的配置+ V* {2 Q( L+ N2 g- K, |
7 t, e* {; G) F/* vim:set sw=8 noet */9 z% s, [3 B# F8 ` n4 d7 ~
4 }/ K2 C1 \1 p
; }" _7 p- e1 l) e) u2 d2 |每个人使用的开发工具可能都不一样, 这样的配置对有些人来说就是垃圾
" X& S/ A/ e/ S y2 G3 [ A5 p4 T6 l3 t( W; e! _! D
7 I4 ~- h8 f) N% G0 S8 W+ m
. N; J0 T$ t1 y) }5 I8 w0 O内核代码格式化工具介绍
3 s3 c7 y% Q; A( e8 n0 u; _checkpatch.pl - 检查source或者patch是否符合规范4 @& N5 a: Z7 \% [* U& `
Lindent - 格式化代码的缩进
* ^) n% s& @# O! \' x
+ f3 _: P% D9 L4 C3 M& C2 `( ? n- i. q. T2 t6 x
这2个工具都在内核代码树中的 scripts 文件夹中。 |
|