日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

请善用工具审核您的内核代码:)

發(fā)布時間:2025/7/25 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 请善用工具审核您的内核代码:) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在寫內(nèi)核代碼時。代碼風(fēng)格(coding style)是一個非常重要的部分,否則內(nèi)核代碼將變的混亂不堪。

那么什么樣的代碼算美麗的代碼?什么樣的代碼符合c99這種標準?此外,程序?qū)懲曛?#xff0c;有什么工具可以幫我們檢查代碼有沒有指針錯誤?客官且隨我看看這三個工具:

1. 代碼風(fēng)格篇

想開發(fā)一個內(nèi)核程序?你的電腦有內(nèi)核源代碼么?無論是以前用來編譯內(nèi)核或者你自己查閱資料,假設(shè)您的電腦上有內(nèi)核源代碼,好的,本節(jié)將介紹一個非常多人都不知道的強大的工具 -- checkpatch。

So, where is it ?

ok ,打開內(nèi)核代碼,cd 到 “ scripts?”文件夾下,查看有木有checkpatch.pl 文件?

How to use ? Yup, very easy ! Please use " patch-to-kernel/scripts/checkpatch.pl ?--file yourcode.c?" !

還不明確?來看看我怎么用:

~/kernel/linux-3.12.1/scripts/checkpatch.pl --file ../net_drive/netdump.c

那么這個工具有什么好?請看以下這個代碼:

/** file : netdump.c* (C) 2014 Yunlong Zhou <reaper888@yeah.net>* Under licence GPL** Introduction :* This modules will scan netdevices and report them via printk ** Useage: 1. make -- you should make the module firstly(with Makefile )* 2. su -- use root * 3. insmod netdump.ko -- install the module* 4. dmesg | tail -- check the status that module print!* 5. rmmod netdump -- after use ,please don't forget rmmove the module **/#include <linux/module.h> /* MODULE* */ #include <linux/kernel.h> /* printk */ #include <linux/netdevice.h> /* dev_get_by_index */static int __init hello_init(void) {printk("netscan module enter\n");struct net_device *dev;struct rtnl_link_stats64 temp;int idx=1; /* first netdevice if it exists */do{dev = dev_get_by_index(&init_net,idx);if (dev==NULL) {printk("Last netdevice index %d\n",idx-1);}else {const struct rtnl_link_stats64 *stats = dev_get_stats(dev,&temp);printk("%s: ifindex %d\n",dev->name,dev->ifindex);// more in this struct than reported here ! printk("This is the current status jus get !\n");printk("packets:%llu/%llu bytes: %llu/%llu errors:%llu dropped:%llu\n\n",stats->tx_packets,stats->rx_packets,stats->tx_bytes,stats->rx_bytes,stats->rx_errors,stats->rx_dropped);}idx++;}while(dev!=NULL);return 0; }static void __exit hello_exit(void) {printk("netscan module exit\n"); }module_init(hello_init); module_exit(hello_exit);MODULE_AUTHOR("Zhou Yunlong <reaper888@yeah>"); MODULE_DESCRIPTION("scan netdevices and report them via printk"); MODULE_LICENSE("GPL");

寫過內(nèi)核模塊的童鞋能輕易的分辯。這是個內(nèi)核模塊。再有經(jīng)驗的童鞋,可以看出來這個模塊的主要工作都在 init 時做了(也即insmod 模塊時)。

那么做了什么工作呢?事實上非常easy。就是讀取網(wǎng)卡設(shè)備的狀態(tài)然后顯示出來,比方說發(fā)/收多少數(shù)據(jù)包,多少字節(jié)等。并且因為代碼圖簡便,通過 printk 輸出,所以信息僅僅能通過 dmesg查看!

對于有經(jīng)驗的童鞋,會在編譯模塊的Makefile 文件里加入 -Wall 標志(W 即warning,all即全部,所以加入 -Wall 標志位會打印出全部編譯時的警告)。對于這段代碼:

$ make make -Wall -C /lib/modules/`uname -r`/build M=`pwd` modules make[1]: Entering directory `/home/long/kernel/linux-3.12.1-rtpatched'CC [M] /tmp/netdump.o /tmp/netdump.c: In function ‘hello_init’: /tmp/netdump.c:24:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]Building modules, stage 2.MODPOST 1 modulesCC /tmp/netdump.mod.oLD [M] /tmp/netdump.ko make[1]: Leaving directory `/home/long/kernel/linux-3.12.1-rtpatched' $ sudo insmod netdump.ko $ dmesg .... [ 8300.686085] netscan module enter [ 8300.686095] lo: ifindex 1 [ 8300.686097] This is the current status jus get ! [ 8300.686101] packets:888/888 bytes: 282809/282809 errors:0 dropped:0 [ 8300.686101] [ 8300.686105] eth1: ifindex 2 [ 8300.686107] This is the current status jus get ! [ 8300.686110] packets:945987/2384507 bytes: 77162255/3264031681 errors:0 dropped:35 [ 8300.686110] [ 8300.686115] eth3: ifindex 3 [ 8300.686117] This is the current status jus get ! [ 8300.686119] packets:0/0 bytes: 0/0 errors:0 dropped:0 [ 8300.686119] [ 8300.686123] sit0: ifindex 4 [ 8300.686125] This is the current status jus get ! [ 8300.686128] packets:0/0 bytes: 0/0 errors:0 dropped:0 [ 8300.686128] [ 8300.686131] Last netdevice index 4

我們能夠看到,程序編譯時也僅僅提示了一個“ ISO C90 forbids mixed declarations and code?”錯誤,對于有經(jīng)驗的童鞋,能夠非常輕松的排除這個錯誤,就是把提示警告的函數(shù)中全部的聲明部分放在函數(shù)最前面,而其它代碼放在聲明后面。

那么這種代碼在您平時編程中是不是堪稱完美?編譯器不報錯(上述簡單的警告。我們能夠輕松排除)。程序執(zhí)行正常。

那么這樣一段程序?qū)τ?checkpatch 來說是什么樣的?我們能夠看看:

$ ~/kernel/linux-3.12/linux-3.12.1/scripts/checkpatch.pl --file netdump.c > log

打開log 文件:

ERROR: trailing whitespace #7: FILE: netdump.c:7: + * This modules will scan netdevices and report them via printk $WARNING: line over 80 characters #9: FILE: netdump.c:9: + * Useage: 1. make -- you should make the module firstly(with Makefile ) ... total: 22 errors, 16 warnings, 63 lines checkedNOTE: whitespace errors detected, you may wish to use scripts/cleanpatch orscripts/cleanfilenetdump.c has style problems, please review.

最后一行,checkpatch 工具非常輕柔的告訴我們,netdump.c 文件有代碼風(fēng)格問題,請改正吧!

total: 22 errors, 16 warnings, 63 lines checked?”!63行的代碼。有22個錯誤,16個警告!我們能夠先看看ERROR部分(由于ERROR部分是必需要改的,重要的錯誤):

$ grep "ERROR" log | sort | uniq ERROR: code indent should use tabs where possible --- 代碼行前面的空白處應(yīng)該使用TAB 而不是空格 ERROR: do not use C99 // comments --- 不能使用C99中的"//"型凝視,須要使用 "/**/"型 ERROR: space required before the open brace '{' --- 對于 for,if,while等有涉及到代碼段時,使用 { 和 } 時。須要在{ 之前和}之后(假設(shè)后面有東西的話。否則就成了代碼行末尾空白)加空格,比方 if (cond) { ... } else { ... } ERROR: space required after that close brace '}' ERROR: space required after that ',' (ctx:VxO) --- 帶參時,比方foo(a,b),在a,后b之前須要空格,所以正確使用方法是: foo(a, b) ERROR: space required after that ',' (ctx:VxV) ERROR: space required before that '&' (ctx:OxV) --- 此條和上面的帶參反復(fù) ERROR: space required before the open parenthesis '(' --- 相似{} ,()前后也須要空格 ERROR: spaces required around that '==' (ctx:VxV) --- 比較"=="/"!="和賦值"="前后也須要空格 ERROR: spaces required around that '=' (ctx:VxV) ERROR: spaces required around that '!=' (ctx:VxV) ERROR: trailing whitespace --- 代碼行的末尾有多余的空白(空格/tab>)

分析完ERROR。我們在來看看WARNING:

$ grep "WARNING" log | sort | uniq >b -- 吃驚的發(fā)現(xiàn),16個警告去反復(fù)之后僅僅有4類 WARNING: line over 80 characters -- 代碼行多余80個字符!為什么是80個字符。有興趣 能夠去查查(小透露一下,歷史原因。) WARNING: please, no space before tabs -- tab前有空格。全部空格一律使用tab! WARNING: please, no spaces at the start of a line -- 行開始沒有空白 WARNING: printk() should include KERN_ facility level -- printk沒有"KERN_"這種輸出級別!

為>什么這僅僅是warning?大家都知道,假設(shè)printk沒有帶輸出級別,它將採用默認!



如今還敢說你的代碼習(xí)慣非常好么?你能夠試驗一下你最自豪的代碼。祝您玩的愉快


二、 代碼檢測篇

2.1?Coccinelle?

Coccinelle是一個程序的匹配和轉(zhuǎn)換引擎,它提供了語言SMPL(語義補丁語言)用于指定C代碼所需的匹配和轉(zhuǎn)換。Coccinelle 最初是用來幫助Linux的演變,支持更改庫應(yīng)用程序編程接口,比方重命名一個函數(shù)。添加一個依賴于上下文的函數(shù)參數(shù)或者又一次組織一個數(shù)據(jù)結(jié)構(gòu)。除此之外,Coccinelle頁被人用來查找或者修復(fù)系統(tǒng)代碼的bug。

2.1.1 安裝

(1) sudo apt-get build-dep coccinelle?

假設(shè)您的apt-get 提示找不到coccinelle。建議您把你的" /etc/apt/sources.list "配成我這種吧:

$ cat /etc/apt/sources.list deb http://mirrors.163.com/debian wheezy main non-free contrib deb-src http://mirrors.163.com/debian wheezy main non-free contrib

(2) ./configure --enable-release
(3) sudo?make all
(4) sudo make install

2.1.2 使用

事實上Coccinelle使用起來非常easy。比方上面的內(nèi)核模塊代碼。我們怎樣使用coccinelle檢查這段代碼?僅僅須要在編譯時加入coccicheck 選項就可以!

比方,我們的Makefile能夠這么寫:

$ cat Makefile obj-m:=netdump.o default:make -Wall -C /lib/modules/`uname -r`/build M=`pwd` modulescocci:make -C /lib/modules/`uname -r`/build coccicheck MODE=report M=`pwd` clean:make -C /lib/modules/`uname -r`/build M=`pwd` clean
? 這樣。我們能夠使用 make 來簡單編譯模塊,還能夠使用 make cocci 來使用coccinelle對代碼進行檢查:

$ make cocci make -C /lib/modules/`uname -r`/build coccicheck MODE=report M=`pwd` make[1]: Entering directory `/home/long/Mar_class/linux-3.12.9'Please check for false positives in the output before submitting a patch. When using "patch" mode, carefully review the patch before submitting it.make[1]: Leaving directory `/home/long/kernel/linux-3.12.9'


2.2?sparse

Sparse 是用于 C 語言的語法分析器,用以對 C 代碼進行靜態(tài)檢查,它不但能夠檢查 ANSI C 并且還能檢查具有 gcc 擴展的 C 。

在 Linux 中,不但能夠檢查用戶端代碼。還能夠檢查內(nèi)核代碼。起初它由 Linus 編寫,后來交給其它人維護。

Sparse通過 gcc 的擴展屬性 __attribute__ 以及自定義的 __context__ 來對代碼進行靜態(tài)檢查。

以下我們來看看這個奇妙的工具:

2.2.1 安裝

對于sparse的安裝,能夠使用多種方法:

最簡單的一種就是使用apt-get安裝:sudo apt-get install sparse

其次是從站點下載,下載sparse-0.4.4.tar.gz壓縮包后解壓,然后直接 makemake install 就可以!

最后就是使用?git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git 克隆sparse倉庫,然后進入倉庫先使用?git tag 查看最新的版本號。然后使用?$ git checkout -b stable v0.4.4 切到最新的版本號,最后連續(xù)使用root 權(quán)限make make install 安裝即完畢了。

2.2.2 使用

事實上sparse的使用比上面介紹的coccinelle還簡單,僅僅須要在make 后加入 “ C=2 ”。所以上面的Makefile 還能夠擴展成:

$ cat Makefile obj-m:=netdump.o default:make -Wall -C /lib/modules/`uname -r`/build M=`pwd` modulescocci:make -C /lib/modules/`uname -r`/build coccicheck MODE=report M=`pwd` sparse:make C=2 -C /lib/modules/`uname -r`/build M=`pwd`clean:make -C /lib/modules/`uname -r`/build M=`pwd` clean
此時我們僅僅要使用 make sparse 就可以使用sparse工具對代碼進行檢查:

$ make sparse make C=2 -C /lib/modules/`uname -r`/build M=`pwd` make[1]: Entering directory `/home/long/kernel/linux-3.12.9'LD /tmp/test/built-in.oCHECK /tmp/test/netdump.c /tmp/test/netdump.c:23:9: warning: mixing declarations and code /tmp/test/netdump.c:29:48: warning: incorrect type in argument 1 (different base types) /tmp/test/netdump.c:29:48: expected struct net *net /tmp/test/netdump.c:29:48: got struct net extern [addressable] [toplevel] init_netCC [M] /tmp/test/netdump.o /tmp/test/netdump.c: In function ‘hello_init’: /tmp/test/netdump.c:23:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] /tmp/test/netdump.c:29:4: error: incompatible type for argument 1 of ‘dev_get_by_index’ In file included from /tmp/test/netdump.c:18:0: include/linux/netdevice.h:1795:27: note: expected ‘struct net *’ but argument is of type ‘struct net’ make[2]: *** [/tmp/test/netdump.o] Error 1 make[1]: *** [_module_/tmp/test] Error 2 make[1]: Leaving directory `/home/long/kernel/linux-3.12.9' make: *** [sparse] Error 2
由于sparse是對屬性進行檢查,所以在上面使用 make sparse 之前,我把代碼第29行“?dev = dev_get_by_index(&init_net,idx); ”中的& 去掉了,所以sparse會檢測出參數(shù)格式錯誤!

所以你能夠想象,你的代碼中假設(shè)指針使用錯誤,sparse都會一一指出哦!

是不是非常幸福?

注:如今貌似也有針對其它語言的sparse工具,前幾天剛看到有python的sparse,只是還沒嘗試過。


三、總結(jié)篇

使用第一節(jié)中的checkpatch是讓我們養(yǎng)成好的代碼風(fēng)格。既美觀又符合內(nèi)核中的代碼風(fēng)格,何樂而不為?事實上,不管是對于已工作的程序員還是對于要找工作的學(xué)生來說,養(yǎng)成好的代碼習(xí)慣和風(fēng)格總是好的。最大的優(yōu)點是讀代碼方便。其次是好的代碼風(fēng)格能夠讓別人對你有了最主要的認識!

第二節(jié)中的兩個工具都是由來已久,并且在內(nèi)何編碼界使用也非常廣泛,假設(shè)你每次都使用這兩個工具檢查。相信對你的代碼能力也會有非常大的提升。

最后送大家一句: 學(xué)習(xí)easy,堅持不易。且學(xué)且珍惜!


==================

很多其它閱讀:?

[1] http://kernelnewbies.org/KernelHacking

[2]?http://coccinelle.lip6.fr/

[3]?https://home.regit.org/technical-articles/coccinelle-for-the-newbie/

[4]?http://kernelnewbies.org/Sparse

[5]?http://www.cnblogs.com/wang_yb/p/3575039.html


轉(zhuǎn)載于:https://www.cnblogs.com/bhlsheji/p/5386611.html

總結(jié)

以上是生活随笔為你收集整理的请善用工具审核您的内核代码:)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。