看printk引发的一点思考
生活随笔
收集整理的這篇文章主要介紹了
看printk引发的一点思考
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在源碼位置
函數原型
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,...用法舉個例子
#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 請按任意鍵繼續.?.?.再舉個例子
#include?<stdlib.h> #include?<stdio.h> #include?<stdarg.h> int?maxof(int,?...); void?f(void);/*主函數*/ 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 請按任意鍵繼續.?.?.說點自己的理解
作為初學者,第一次看到
fmt,...這樣的寫法,心里就會有點懵逼,但是實際上,你把它作為C語言的一個知識點,記下來了,就沒有那么困難了。既然作為可變參數標識,那么函數體里面,自然也需要解析的方法,我上面寫的那個例子,就是解析的方法。
不管是Linux 內核里面的printk函數,還是我們平時調試打印的printf函數,他們都是一樣的原理。
解析可變參數
解析就離不開這三個宏
va_list?ap; va_start(ap,?n_args); va_end(ap);這里面需要涉及到一些技巧,這篇文章里面就不解析說明了,printf 和printk里面使用的還有些差異,無非就是C語言的奇淫異巧,把這種普通人理解不了的東西形容為降龍十八掌,九陰真經,我覺得并不為過。
Linux 驅動打印日志加上自己的TAG
好了,直接上代碼就好了,我們平時打印的時候都是直接用一個printk,也沒有經過封裝,代碼這種東西,你要是把它看作是一個藝術品也并不為過,所以很多人談到一個詞,叫做技藝,你自己把這種知識點都掌握了,自己的技藝也就會得到提升了。
#define?LOG_TAG?"[ES7243]:?%s()?line:?%d?"? #define?Log(fmt,?args...)??printk(KERN_INFO?LOG_TAG?fmt,?__FUNCTION__,?__LINE__,??##args)## 這個符號的作用
在C語言里面,## 有兩個作用
在函數里面和可變參數一起使用,如果可變參數沒有傳參,這個符號就把前面的 「,」去掉,這樣編譯就不會出錯。
如果是宏里面使用,就起到一個拼接字符的作用
舉個例子
#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 請按任意鍵繼續.?.?.推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
嵌入式Linux
微信掃描二維碼,關注我的公眾號
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的看printk引发的一点思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Luyten 启动报错 This App
- 下一篇: python定时任务启动与停止_Pyth