看printk引发的一点思考
在源碼位置
函數(shù)原型
asmlinkage?__visible?int?printk(const?char?*fmt,?...) {printk_func_t?vprintk_func;va_list?args;int?r;va_start(args,?fmt);/**?If?a?caller?overrides?the?per_cpu?printk_func,?then?it?needs*?to?disable?preemption?when?calling?printk().?Otherwise*?the?printk_func?should?be?set?to?the?default.?No?need?to*?disable?preemption?here.*/vprintk_func?=?this_cpu_read(printk_func);r?=?vprintk_func(fmt,?args);va_end(args);return?r; } EXPORT_SYMBOL(printk);fmt,...用法舉個(gè)例子
#include?"stdio.h"void?tfunc(const?int?fmt,...) {printf("tfunc...\n"); }?int?main(void) {tfunc(12);tfunc(12,13);tfunc(12,13,14);return?0; }?輸出
tfunc... tfunc... tfunc...-------------------------------- Process?exited?after?0.04347?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.再舉個(gè)例子
#include?<stdlib.h> #include?<stdio.h> #include?<stdarg.h> int?maxof(int,?...); void?f(void);/*主函數(shù)*/ int?main() {f();exit(EXIT_SUCCESS); }int?maxof(int?n_args,?...) {register?int?i;int?max=0,?a=0;va_list?ap;va_start(ap,?n_args);max?=?va_arg(ap,?int);printf("max:%d?a:%d?n_args:%d\n",max,a,n_args);for(i?=?1;?i?<?n_args;?i++){if((a?=?va_arg(ap,?int))?>?max){max?=?a;}printf("[%d]?max:%d?a:%d\n",i,max,a);}va_end(ap);return?max; }void?f(void)? {int?i?=?5;int?j?=?26;printf("\nmax:%d\n",maxof(3,i,j,13)); }輸出
max:5?a:0?n_args:3 [1]?max:26?a:26 [2]?max:26?a:13max:26-------------------------------- Process?exited?after?0.0439?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.說(shuō)點(diǎn)自己的理解
作為初學(xué)者,第一次看到
fmt,...這樣的寫(xiě)法,心里就會(huì)有點(diǎn)懵逼,但是實(shí)際上,你把它作為C語(yǔ)言的一個(gè)知識(shí)點(diǎn),記下來(lái)了,就沒(méi)有那么困難了。既然作為可變參數(shù)標(biāo)識(shí),那么函數(shù)體里面,自然也需要解析的方法,我上面寫(xiě)的那個(gè)例子,就是解析的方法。
不管是Linux 內(nèi)核里面的printk函數(shù),還是我們平時(shí)調(diào)試打印的printf函數(shù),他們都是一樣的原理。
解析可變參數(shù)
解析就離不開(kāi)這三個(gè)宏
va_list?ap; va_start(ap,?n_args); va_end(ap);這里面需要涉及到一些技巧,這篇文章里面就不解析說(shuō)明了,printf 和printk里面使用的還有些差異,無(wú)非就是C語(yǔ)言的奇淫異巧,把這種普通人理解不了的東西形容為降龍十八掌,九陰真經(jīng),我覺(jué)得并不為過(guò)。
Linux 驅(qū)動(dòng)打印日志加上自己的TAG
好了,直接上代碼就好了,我們平時(shí)打印的時(shí)候都是直接用一個(gè)printk,也沒(méi)有經(jīng)過(guò)封裝,代碼這種東西,你要是把它看作是一個(gè)藝術(shù)品也并不為過(guò),所以很多人談到一個(gè)詞,叫做技藝,你自己把這種知識(shí)點(diǎn)都掌握了,自己的技藝也就會(huì)得到提升了。
#define?LOG_TAG?"[ES7243]:?%s()?line:?%d?"? #define?Log(fmt,?args...)??printk(KERN_INFO?LOG_TAG?fmt,?__FUNCTION__,?__LINE__,??##args)## 這個(gè)符號(hào)的作用
在C語(yǔ)言里面,## 有兩個(gè)作用
在函數(shù)里面和可變參數(shù)一起使用,如果可變參數(shù)沒(méi)有傳參,這個(gè)符號(hào)就把前面的 「,」去掉,這樣編譯就不會(huì)出錯(cuò)。
如果是宏里面使用,就起到一個(gè)拼接字符的作用
舉個(gè)例子
#include<stdio.h>#define?LOG_TAG?"[ES7243]:?%s()?line:?%d?"? #define?func(fmt,?...)?printf(LOG_TAG?fmt,?__FUNCTION__,?__LINE__,??##__VA_ARGS__) #define?acpi_handle_debug(?fmt,?...)?printf(?fmt,?##__VA_ARGS__) #define?debug(...)?printf(__VA_ARGS__)#define?_TEST_(x)?x##2 int?main() {int?i?=?23;func("adf:%d\n",++i);debug("123:%d\n",++i);acpi_handle_debug("4444\n");func("%d\n",_TEST_(1));return?(0); }輸出
[ES7243]:?main()?line:?12?adf:24 123:25 4444 [ES7243]:?main()?line:?16?12-------------------------------- Process?exited?after?0.03505?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語(yǔ)言
嵌入式Linux
微信掃描二維碼,關(guān)注我的公眾號(hào)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的看printk引发的一点思考的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Luyten 启动报错 This App
- 下一篇: 小米19999