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