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

Linux 内核Coding Style整理

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
3 P4 t; F/ @7 |& _
总结linux内核开发的coding style, 便于以后写代码时参考.
8 s# p0 }6 m- Q  r& {! g4 _
$ f& w3 U* P$ X9 I9 Q下面只是罗列一些规则, 具体说明可以参考: 内核源码(Documentation/CodingStyle)
1 n( B. G) g# r
' E' i1 V8 ^% ~2 V' B, C
( U3 y  o4 x: m) p1 q) R$ b0 `* J/ g
01 - 缩进9 Q. I" O2 c  q6 o
缩进用 Tab, 并且Tab的宽度为8个字符- r9 W$ v& J  C! O% m' p$ k6 V
swich 和 case对齐, 不用缩进
6 Y' l4 Z; t6 U% z  K复制代码
( v, n7 }+ V! X) ]: D) bswitch (suffix) {) X$ z; J2 n$ i5 C
case 'G':
7 W! z" k- Y* F) F6 {/ n3 icase 'g':
/ o- A: V7 J, o8 R% k        mem <<= 30;0 G, c( o4 ]# x0 U' D7 @
        break;3 A$ o: b% E3 S7 t' w
case 'M':, Y! o6 W1 `/ }. {  b+ E4 a- G+ h
case 'm':3 n1 ]8 ^% K9 x0 V- k0 ]
        mem <<= 20;8 X5 A2 O" n* Y) u0 n1 h
        break;
2 u! p6 H/ s0 J7 f# xcase 'K':
' n/ ]5 v& }2 X, X3 ^+ Vcase 'k':0 B) j- ^0 Z/ Z/ v
        mem <<= 10;6 W3 L6 Z# i* A# Q0 K8 B
        /* fall through */. P2 Y. r* w# P9 e( F$ B
default:& B) |  Q4 C/ ~
        break;
1 {: M5 {- G5 H. R}) w  A7 r- d9 @' V: X$ a+ @* e, S- J
复制代码
$ G3 {: U" W1 g9 S% H0 T- H! b
) ]' Z0 e% S  Z' a( _5 d" H, F. i0 f7 c$ O( y" H
一行只有一个表达式+ G. S. ?+ J: v5 Q. \
if (condition) do_this;  /* bad example */" R% `0 K: A; |2 ~

  k, P* B/ k4 ^( F! J7 O; {( ]( T0 V5 j( t# M- b# V7 G1 Q
不要用空格来缩进 (除了注释或文档)
* _4 {3 c; M4 R  M
0 g0 w9 J* ]$ I5 Y9 T5 K: a* K' J+ ]
02 - 代码行长度控制在80个字符以内
0 k) ^$ X( O+ h# Q. A长度过长的行截断时, 注意保持易读性
- w, D9 d  w$ S
- a3 v4 ]- I4 L* ^/ n复制代码: n/ n* N  w. l0 d- ?5 @& r; v
void fun(int a, int b, int c)9 K; u, h; I: w6 O! m
{
6 f! @' Y5 ~. j; T9 ]9 Z        if (condition)* ]$ G7 O5 `  u* i: @3 }- Z5 R% O
                printk(KERN_WARNING "Warning this is a long printk with "+ T) w! Y+ z+ ^8 \, ^* W3 \+ Y
                       "3 parameters a: %u b: %u "5 O0 I2 `# [$ R: E) R2 b1 X
                       "c: %u \n", a, b, c);
' Y0 q' C9 ?- ]' {, S: B* k        else
# }) s2 I6 X2 m; x                next_statement;
" K6 q% b) u( h" h}  `* K" z- M- C# g  X) d* c; `
复制代码
  {% N& p- M' u! d( u
9 R7 V5 E) C5 H% d; E
5 x$ |) r2 F0 J/ d/ d03 - 括号和空格的位置
: `  V) b' F, }  L& R函数的大括号另起一行: o* F5 I) r4 z& Q: v8 E4 w+ f$ i
int function(int x)
* P, _- a6 Z0 H% _) Z{   /* 这个大括号 { 另起了一行 */
" n1 ?/ L, s. k/ N' p        body of function8 B: t; e+ C4 {7 _
}" _4 A/ V1 A  C& _
( e: l2 ]3 z. c; G4 o% ?# p' f

- y7 U: }# `+ k6 U0 A3 ?2 x1 J) a非函数的语句块(if, switch, for, while, do)不用另起一行
1 g  g# h! m5 H+ @3 S5 e- M; nif (x is true) {  /* 这个大括号 { 不用另起一行 */+ t: @+ E* z  g% E5 t2 ~6 D
        we do y! c& r4 `7 V  n3 t; i
}& a0 c& m( l% d

9 h+ c5 E! f6 V# L, `* t- Q$ r% m3 S% @6 }2 ]$ i* c; J
只有一行的语句块不用大括号( \9 s3 ^1 T; i; ^
if (condition)
! O4 ]5 J# Y- |+ V; S( h7 u$ x: J        action();5 d$ h# n7 A. D/ N% P

+ f7 d! s2 W2 B/ t8 L; M
8 o9 W; I2 @' q! j如果if用了大括号, 那么else即使只有一行也要用大括号
6 Y3 c# t" }8 K. J, y& `  Mif (condition) {
/ G( T7 A6 j  [0 z2 y& o        do_this();
! V& C7 [6 u; S3 B( b4 e        do_that();
* ?  e  m! Y) ?9 U} else {9 v4 M( U4 o" B1 S; S2 D3 c8 x6 _* }/ z
        otherwise();
" f* }% y6 k+ u! `& |/ Z/ @}  ?/ P) l/ B- v" A
! R& X$ Q. u0 [; x
- a0 z. Q& O# @4 x
下列 keywords 后面追加一个空格: R9 l+ a* r, h8 q
if, switch, case, for, do, while
. ]( l# Z" @  Z8 M0 X
4 r4 ?. X0 T1 g+ ~) M 0 k" K4 F; w3 O' N

3 X7 ~0 O! e( O: x5 v+ Y下列 keywords 后面 *不要* 追加一个空格5 \3 U$ L- g: d8 z& D( U' P
sizeof, typeof, alignof, __attribute/ _0 r5 `9 `# I4 \

5 O  B6 ^0 p$ w* J7 O1 Ps = sizeof(struct file);    /* good */
# x& s3 N: b6 V3 as = sizeof( struct file );  /* bad  */
  i, I9 M2 p1 f' i- ?9 u
0 E/ S4 `- T6 D8 ^- C5 g) r: m' ^' c! K* Y
定义指针时, * 紧靠函数名或者变量名
' Q- q6 U; |+ n) O9 L+ @  vchar *linux_banner;
6 u" v# I# O2 f" `  H4 I/ I9 cunsigned long long memparse(char *ptr, char **retptr);2 @* N% K# h: l
char *match_strdup(substring_t *s);
) l9 E+ c/ c: n& E* ]! V
/ V+ z, _! n$ w( F) ^
. r! F/ U$ {* b) C, P% r! H9 Q; r4 v下面的二元和三元操作符左右要留一个空格+ o8 ~- `$ p4 C( X
=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :9 N% H* G; x6 I7 J5 c3 q

7 j% J* z% U6 Q/ J  t8 s! b# D
8 j" T1 N/ u' j8 y. @+ T$ T8 y* L. X9 N& E3 ]5 Z* h, S) p% o
下面的一元操作符后面 *不要* 留空格# g: C# Z# G$ O4 L* {
&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
* x8 o7 L6 M5 P+ s( `& y) B! o' o4 N  N1 B
( g2 `. D( {8 E5 T; n# V7 X, e
0 [2 v- B8 G9 \/ }0 F- e+ J
后缀操作符(++ --)前面不要留空格, x& u. w* Q$ f' S8 b1 H
$ D$ X5 k3 c( T8 f
9 J! x' e& g. m- ^# U
前缀操作符(++ --)后面不要留空格
: g0 }2 C8 I# H- p7 k. w8 S
0 u; @( ]6 r+ h! _
5 B* }. G$ D( f# U结构体成员操作符(. ->)前后都不要留空格
- X- J' f/ g$ D0 @ 7 {) c, Q/ g1 p8 v4 s4 Q1 Y
8 g9 R9 K5 U$ v! _6 b1 A/ m1 ^
每行代码之后不要有多余的空格4 D9 R4 w% r. j( A0 f

2 h1 C& X* Z3 g% {
9 s9 a3 [2 @$ E6 J8 D+ K04 - 命名5 B9 U, L* R: Q6 W0 |6 s7 y
全局变量或函数(在确实需要时才使用)要有个描述性的名称
/ E. J# g- z6 O' t& `4 u/ l" tcount_active_users()  /* good */
) y+ \8 X9 H! I3 Dcntusr()              /* cnt  */
* V" [2 W; i* }3 O# }+ U+ b: {* ` 4 f& e% U$ A% e- u6 b* x6 m
/ W& t8 @1 G8 |, [" S$ [
局部变量名称要简洁(这个规则比较抽象, 只能多看看内核代码中其他人的命名方式)6 q$ ~2 T7 b1 _) m, L- r& Y, T
" j3 S& L: ]1 n" C' w9 W8 H
# B3 b( A  Z6 _1 z) R! ~& l% F
05 – Typedefs
6 _0 a+ p1 ]3 R尽量不要使用 typedef, 使用typedef主要为了下面的用途:3 ~% d! [+ Y  z9 \0 M5 y5 X
( j, g0 S- ^  T* W& ~/ ^
1. 完全不透明的类型(访问这些类型也需要对应的访问函数)
' j3 ]0 [, s% k% x! _* L# O2 k1 ^  E1 X! e" F  ~
    ex. pid_t, uid_t, pte_t ... 等等
% p* t& F' k9 E6 m" K; f) a' r4 v3 M' k  r5 j  o: j
2. 避免整型数据的困扰
) N1 t0 @" [4 p5 z$ E0 d+ m9 [  D0 V
! F$ j! M# B! b4 o! \2 u5 ^* F5 ~8 a    比如int, long类型的长度在不同体系结构中不一致等等, 使用 u8/u16/u32 来代替整型定义( m0 @  Q( O: E5 i9 n* c  ]2 K
* L! n6 Y9 D9 [' ~# s. K  |
3. 当使用kernel的sparse工具做变量类型检查时, 可以typedef一个类型.
- x5 Q5 v2 r6 [) l, k& _6 l. c; C  _
0 A( O0 s8 Y, g$ ^( p5 _" F* @4. 定义C99标准中的新类型/ T9 K% q7 F/ L3 Q8 @! z6 @( b
% C8 T6 H0 x3 V# H" H
5. 为了用户空间的类型安全
* G- j- I& a: y+ {
7 w* m+ F% c. t" f! z2 d    内核空间的结构体映射到用户空间时使用typedef, 这样即使内核空间的数据结构有变化, 用户空间也能正常运行
( ^) {- {$ v9 K! b; @/ A- o; E1 X. F* X- G' H
; E/ X' s4 v( I/ v( @6 H

/ Q  o9 N7 |7 Q) p5 u* B' C06 - 函数
9 O0 O, k& M6 v. g6 }函数要简短,一个函数只做一件事情3 [" o5 K- I/ v( g7 D
% y& e7 O3 b, c# E0 e
2 e% \( b/ F+ a' @# Q
函数长度一般不超过2屏(1屏的大小是 80x24), 也就是48行
" \: K5 Q% ?; [: u 0 v" E9 F) z% o
# U  {7 u" @  ?6 W; \
如果函数中的 switch 有很多简单的 case语句, 那么超出2屏也可以
2 @7 k' Q" ~7 b) Z/ j& S9 {
" \2 [- ~( R/ D8 P1 e3 I6 m9 B/ G7 V' R2 S8 w" T
函数中局部变量不能超过 5~10 个
1 t3 Y( S+ m! Y" }) ]
# c+ L) M8 e4 C- u# B9 T7 R  f7 Q, D2 a% O2 W
函数与函数之间空一行, 但是和EXPORT* 之间不用空$ B* t/ i4 W9 Q5 E. C: g" F, Y
复制代码
2 E" C. n; K  e+ Pint one_func(void)& N) [7 z: w, q; q
{
% }) h  m. q% j' a. e& W; w        return 0;
( F2 s: g1 ^) f- r& t/ V: X: l' ~}* x2 h) g! b* P, Q
8 L1 H# d5 T6 o; u
int system_is_up(void)7 c$ l; r; K& z/ `, b2 x6 \1 m" K
{
  |$ q) q4 H  m! q8 L- X        return system_state == SYSTEM_RUNNING;! R8 P. Y4 N, ~5 v
}
9 G0 x  b& }" N8 }8 f2 L$ z5 ~EXPORT_SYMBOL(system_is_up);1 j, G) `& A* I$ x& I: c7 N
复制代码3 t5 \4 r# q) J/ i' N) C
  N7 k) K; C: ^& V9 u$ Y' @+ j

  E5 O; A+ I3 u8 Y07 - 函数退出
3 ?/ Z$ a! j7 h% k将函数的退出集中在一起, 特别有需要清理内存的时候.(goto 并不是洪水猛兽, 有时也很有用)
3 |% M! t2 [# x% x% H" q
$ C" }' z4 g& t$ B: Q1 C( f8 L- d复制代码5 c# W3 O! z0 V* w% ?" m
int fun(int a)+ W7 V0 A  _% m# ?9 K
{
8 \% O* L4 N& w, x8 z% m! b        int result = 0;
6 T4 p! n* v1 j9 T        char *buffer = kmalloc(SIZE);
$ ]; w  O3 i% ~2 A
1 ^' B* b6 y4 ?5 t7 B        if (buffer == NULL)
# R) n- {) ~" s2 G. C                return -ENOMEM;
& z# }' p% l  V0 T. U; J4 r1 X" d; P% w0 p4 S  Q& U( _
        if (condition1) {
1 D0 [5 [4 C( w: l7 p! ^1 b  v) Y  b                while (loop1) {% N/ W2 R6 s1 v$ K, I
                        ...
2 }2 [: l$ d( U0 Y; [) @( B/ N                }" |# l# `& i! f, {
                result = 1;
: o: }4 N* ~* _4 D  s* I                goto out;
: h6 e; E: @& a) e  D! E        }# [2 O: |( n. X! h
        ...
7 ]3 l' k/ }* l$ I; l        out:% ?7 T/ x9 C/ D  U2 V
                kfree(buffer);  b& `" Q0 ]9 f; W- [2 b: g. o6 F
                return result;
$ a! O* n) u1 d7 X8 F}
+ m2 ^8 X& F6 I& D: C4 o0 l6 \复制代码* o$ x$ V9 n% {- K

& L/ ~7 ?( s0 f" u& q; F) ?
. k# L: \/ z# m# }08 - 注释
% F  N* _. R9 B0 [- B6 x# a注释code做了什么, 而不是如何做的
  m2 z$ o( E: T  n6 ^- ^! {, C6 {1 c
0 I0 ^) G1 J: ]5 C; D
, e( n: B) D: i7 |使用C89的注释风格(/* ... */), 不要用C99的注释风格(// ...)
$ Q1 C; A# T+ h, U1 h" A 2 ~: j: e" y+ H* r5 R
# {: \$ e& o$ x, N! ~1 H4 R2 T
注释定义的数据, 不管是基本类型还是衍生的类型3 i- t# v8 T3 A7 h

% E) {! Q9 |7 t2 O1 z6 S: g5 o  \" e7 {  q: k
09 - 控制缩进的方法
" w+ T8 a) E; F5 w用emacs来保证缩进, .emacs中的配置如下:, K8 T& m4 J  y
复制代码/ C. q# }# J; r6 [( i
(defun c-lineup-arglist-tabs-only (ignored)1 h) k0 y% a: p8 V* M
  "Line up argument lists by tabs, not spaces"
9 ^/ a8 ^) a0 _: A( U5 S* y6 R( E) a  (let* ((anchor (c-langelem-pos c-syntactic-element))
6 z' c. M/ F" }: i* l4 X     (column (c-langelem-2nd-pos c-syntactic-element))
2 I. L. b% ~8 Y6 V3 z& X     (offset (- (1+ column) anchor))
" J2 ?& J! v) w- `" Z2 F- h/ i1 B     (steps (floor offset c-basic-offset)))
- R* y# `2 S' E" s/ j9 ]' T$ }    (* (max steps 1)
4 O) S0 \$ T+ O9 R( V       c-basic-offset)))
6 }8 B4 ~. ]5 `( ~# r# \  o2 z  R* w) {0 H1 Z
(add-hook 'c-mode-common-hook& E8 H) l! \! X
          (lambda ()8 v3 ^: s. _! X/ j8 h$ Y. B
            ;; Add kernel style
4 U5 u! L0 L3 x            (c-add-style
' f3 t. O+ f4 N9 o; Q             "linux-tabs-only"7 w) s; T$ ?& ]; x) {' Q
             '("linux" (c-offsets-alist, s' w+ {! a* v
                        (arglist-cont-nonempty
& _' d9 Z1 p6 J                         c-lineup-gcc-asm-reg
; I8 o, L4 n& r  B                         c-lineup-arglist-tabs-only))))))
* s  e9 r# F/ u/ l  p6 i! g8 q
! a1 c/ V5 Z& i- F(add-hook 'c-mode-hook) K, |$ B4 [9 T4 y
          (lambda ()
  y; K+ ?$ i$ l  t" W' C4 n  D            (let ((filename (buffer-file-name)))- \0 Z$ P, a: f, z; ]
              ;; Enable kernel mode for the appropriate files
/ ~8 H0 e6 D! S              (when (and filename
- E: x# G4 C9 A6 j  v                         (string-match (expand-file-name "~/src/linux-trees")9 v0 g" X3 x9 K. U2 J# r, Z
                                       filename))2 X9 o0 }3 [, e3 _
                (setq indent-tabs-mode t)" ]' Z2 U9 _/ H- e! h
                (c-set-style "linux-tabs-only")))))$ L1 \) u# I- f  v
复制代码
6 c1 z" `( g3 e: c( C
1 j, ^7 F. g3 H+ v- m( }( W4 y9 V- S6 V# B( P- }# n
使用 indent 脚本来保证缩进. (脚本位置: scripts/Lindent)2 I: C) H* b# ~, Z/ b* m+ B6 [

* \+ J) s+ m* G' S; |8 W) R4 i) m+ ]4 ]4 S: h# t* ~
10 - Kconfig配置文件( P  z! O! L' ]. F) e
"config" 下一行要缩进一个Tab, "help" 下则缩进2个空格, Z7 X, w& {) W; L# N. l- f
复制代码
3 D, J* W' _* G# W# p) hconfig AUDIT
. p, M; w1 y) @9 v1 y: i        bool "Auditing support"# E' k- F0 a4 p% y
        depends on NET. Z( G  h' `; r. k8 Z
        help
5 M! |7 ]) [% x% L          Enable auditing infrastructure that can be used with another* ?4 d5 ^( W$ ?  f7 c* |
          kernel subsystem, such as SELinux (which requires this for
' L5 e0 ?1 M8 o7 g* r  p  `% L          logging of avc messages output).  Does not do system-call
3 L/ ]- w! W5 g! _0 q          auditing without CONFIG_AUDITSYSCALL.. y& ?; Q' n" z+ k; f2 f6 u
复制代码
0 ~/ C3 |, l: R
& v2 Q# n, B2 D, ^4 @7 f8 d; L5 @
不稳定的特性要加上 *EXPERIMENTAL*, S* k, S! q# ?
config SLUB6 D* [" `9 P# m
        depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT- k4 `' w9 O3 I* i7 k
        bool "SLUB (Unqueued Allocator)"" d; p# L/ X& h- g6 S$ V  i, E
        ...
5 {# O* X4 e  g7 g- S7 L 3 n: M) x. o, b' U: C

3 x. s; i* o7 U* @5 k危险的特性要加上 *DANGEROUS*% ?, w; W: W# b* k) [: x
config ADFS_FS_RW
7 Z7 s- F2 V+ R) Z/ k- R        bool "ADFS write support (DANGEROUS)"" @& F2 a2 F2 F
        depends on ADFS_FS$ O2 A: c% Y$ D! W* P/ w- P$ a; c, H
        ...
. }1 I3 p: @% H) k6 x6 R$ F
$ u# W4 E2 l7 @' B7 H  |3 ?7 K9 p8 h' v: l' ^- K
Kconfig的说明可以参见: Documentation/kbuild/kconfig-language.txt
8 K; M! b5 J* R/ L0 N4 [. a, s  X# p! p  i

0 ~2 s" z7 R  V) Z5 p9 O; W1 f
9 n  ~! g  V( [, x& ?11 - 数据结构" C, c7 A7 C; Z
结构体要包含一个引用计数字段 (内核中没有自动垃圾收集, 需要手动释放内存)
$ ]9 |  ~' J- w' E( L
1 a, U( r" p1 P6 h3 i1 r% D( \7 Z6 H4 e/ m! Q' Z- x) M/ _
需要保证结构体数据一致性时要加锁
6 g9 a) \7 v% d/ X$ v( Z) A( P 9 l) {- u: }4 t: L2 _+ J

7 l, B7 g3 T# g结构体中有时甚至会需要多层的引用计数
2 U4 m5 d7 M) \( D5 Dex. struc mm_struct, struct super_block5 t7 A& l! z/ E" a4 {( O

, L1 w, R3 Y# Q4 J; i: y! ^
& ~- y5 F- Z! `- f; T7 b# F, G# M7 r
2 W3 {. R0 X$ N: [6 o4 y/ B12 - 宏, 枚举类型和RTL; B$ ?) R# r2 D5 l7 P' \
宏定义常量后者标签时使用大写字母. I% J: b- J$ B; n1 _! t4 Q( ?
#define CONSTANT 0x12345' v4 l3 ]2 o3 F( D0 H+ N$ S% `" o/ |  I

6 m; l2 S6 R5 [0 i' a5 ]; G2 `1 o+ W# k4 x4 ]7 N
宏定义多行语句时要放入 do - while 中, 此时宏的名称用小写
+ o  M- e4 U9 Z) T: m; H#define macrofun(a, b, c)             \
. A: M9 @( z) \0 x4 L7 i( G    do {                    \
) E; `7 ~" j4 z/ d2 j9 r! m        if (a == 5)            \
# F% C  W8 O4 J6 L; P! p            do_this(b, c);        \# L* L" M' v" {: f6 f6 k
    } while (0)
. v0 k! B/ c7 J  j9 v8 z& U
1 k- ~  O; f/ B; q+ ?  o2 J5 ^! ]4 k3 S0 U
宏定义表达式时要放在 () 中
) f9 Q7 w/ D( Z. ~% E#define CONSTANT 0x4000
4 F$ s) p. z1 I4 Q: `# w#define CONSTEXP (CONSTANT | 3)
( `9 r0 Y  P* Z2 p2 }8 a ! I/ U# @. `* `3 I* k+ K
8 k( R/ y# [& o& D
枚举类型 用来定义多个有联系的常量
+ p; S5 j" _& W. Z# L+ |6 d" v  z7 a * Y, ]( d# `. A; y! o& o% V

5 P4 {) S+ P1 W' G1 Q  w13 - 打印内核消息4 k! m- F) T4 L0 V
保持打印信息的简明清晰
  S3 U) g6 F9 e) M7 ~比如, 不要用 "dont", 而是使用 "do not" 或者 "don't"' @' g0 s) m, O0 p/ m

. ~1 V. s7 M$ V- G' {! T& `0 u
% r5 S  E! a9 \% @/ c: w/ o+ k7 R2 U, f, ]4 z$ A. t
内核信息不需要使用 "." 结尾
, c. @7 I8 `3 w/ P" P
3 ?5 n$ J" v( Y" |' j/ J7 R
+ j$ {+ W/ M( l9 H/ l; U$ k打印 "(%d)" 之类的没有任何意义, 应该避免
8 ^4 h1 Q1 j* i- Y8 E. c) W ! `0 Z2 d1 R9 e$ Z" {: v& P
# {, T, J' w0 ?. l  ?  |; M/ Q
选择合适的打印级别(调试,还是警告,错误等等)
% x# [8 b  l" U7 c8 q* m # E" ~  B% ?. y* t0 i" |' t

+ i# w8 \6 d4 N4 B14 - 分配内存
2 D/ v0 g5 i, u& n; n# Q" \- i7 B分配内存时sizeof(指针) 而不是 sizeof(结构体)& m9 i. {0 }& k1 x) Z+ {, }* \- v
p = kmalloc(sizeof(*p), ...);
# a# C$ q! l% H这样的话, 当p指向其他结构体时, 上面的代码仍然可用1 s" {3 I% c. m' H

, G7 N4 d# L/ _ . `5 `! n; h% ^! X" o

1 D& H1 t0 p1 c1 M2 F分配内存后返回值转为 void指针是多余的, C语言本身会完成这个步骤
  |) {7 A8 J+ ~1 h( d! t" Q% V " E& i1 ^: `" O2 i* R: t) f! i( n

* C- w$ T3 \% d2 a0 c6 m15 - 内联的弊端) s% U; M: v/ Z% D
如果一个函数有3行以上, 不要使用 inline 来标记它4 \0 f* J! @& M  Y+ I2 {
( d0 i6 ~8 }, N( G) P+ B% ~& `

7 c4 l3 ^5 A4 J; a
) k( N, z1 T2 p2 u# a/ a16 - 函数返回值和名称
9 K, W- p0 Q/ c# F如果函数功能是一个动作或者一个命令时, 返回 int型的 error-code
1 X- N8 Y! u3 n- e0 m比如, add_work() 函数执行成功时返回 0, 失败时返回对应的error-code(ex. -EBUSY)) p  O) Q  \( \

5 Q5 N# j+ {6 p  y: \6 c+ `
( c1 u! G- K. E! G  w$ h, @; D8 l. N8 H* o6 G1 @: |# W1 C
如果函数功能是一个判断时, 返回 "0" 表示失败, "1" 表示成功
7 M; |( W0 d+ O! O% f0 C% p 3 L& B3 T) V$ U8 Z* W0 @( M
. _% M: [  F) ]7 }
所有Exported函数, 公用的函数都要上述2条要求
- S5 v) E! V2 J- K7 t9 ~" a2 b* L9 | ! h) \" d  Q4 t, a/ l; s& \
  Z# {% Y; `- z0 u8 V& v9 w
所有私有(static)函数, 不强制要求, 但最好能满足上面2条要求8 b  E+ N+ ~) s1 T: S
) P9 c+ Q  G3 y# ?$ X
% ]5 l9 g3 i# @! N
如果函数返回真实计算结果, 而不是是否成功时, 通过返回计算结果范围外的值来表示失败
# ^5 t/ n* U" g0 m) n+ ~% d8 k比如一个返回指针的函数, 通过返回 NULL 来表示失败
7 D( A2 `. }" k( ~: R* M( U5 o# A, o# ~. p# W
# r1 p0 U/ G* H' Q. C" [
! `- }6 H0 c$ `3 X/ j3 M. Z, f
17 - 不要重复发明内核宏( `5 J/ Q! y1 |% F- x" ?# b
内核定义的宏在头文件 include/linux/kernel.h 中, 想定义新的宏时, 首先看看其中是否已有类似的宏可用6 ^4 ]! f4 Q4 E) z3 a4 Q
$ p; N, S/ p& x0 |
% U# [" n. o: l9 E

! k7 e; p% |5 I/ @/ w$ k: ]18 - 编辑器模式行和其他
9 J. }* [! Q( C$ _不要在代码中加入特定编辑器的内容或者其他工具的配置,
7 n6 I; H1 Z2 L+ q: p" D. ^7 j
1 A: D9 [0 U9 ]7 l比如 emacs 的配置* B% ?; E0 _5 k3 P
5 K0 x, D" Y# y# C
复制代码
# }5 y9 U: ?4 q! b  g4 ?- R/ h4 M  g-*- mode: c -*-
3 r$ Q8 P/ {3 H3 m+ }or
1 Z7 d) x( v" N% I! c/*6 s. ~8 k( g. f8 d4 d7 e
Local Variables:8 K! M2 b' I$ }9 e0 `' I' k$ m
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c") t% o+ ~6 O! F, J1 @: i
End:
5 [7 x+ Q5 q+ t2 D" z*/
% ^8 T) }, p% F4 p* ?3 h复制代码. H$ I% x0 `. O; \. N* Z
; a! ^% M! e3 ^. x- {

+ V" n  v4 K: ~3 gvim 的配置6 p, u1 T. @( y" s3 R
# d2 w) T5 L) q- L; b# G; J
/* vim:set sw=8 noet */0 @: r, w" z1 k! t1 X

4 i  I! L" o# [- s" c( t' o2 g  H5 H
每个人使用的开发工具可能都不一样, 这样的配置对有些人来说就是垃圾
* M- N) @5 H) T+ ^1 o( D  }( T' L9 I* n$ _3 c1 ~; H
9 m# D/ Z% a! r

3 U( @# }- j, y6 v5 P8 g内核代码格式化工具介绍
' m( }2 w; m& b0 q7 A" M0 Xcheckpatch.pl - 检查source或者patch是否符合规范
2 b# }3 O; g$ ?  |, z; P0 {/ iLindent       - 格式化代码的缩进& W9 s" b* d0 U

2 p7 A' R1 Q0 u$ p  U
: Z7 M# z1 K: w+ z, b) O" y% K这2个工具都在内核代码树中的 scripts 文件夹中。

该用户从未签到

2#
发表于 2020-9-16 17:43 | 只看该作者
如果函数返回真实计算结果, 而不是是否成功时, 通过返回计算结果范围外的值来表示失败
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-25 00:31 , Processed in 0.171875 second(s), 23 queries , Gzip On.

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

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

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