linux之printk和printf的區別

大部分常用的C庫函數在Linux內核中都已經得到了實現。在所有沒有實現的函數中,最著名的就數printf()函數了。內核代碼雖然無法調用 printf()函數,但它可以調用printk()函數。printk()函數負責把格式化好的字符串拷貝到內核日誌緩衝上,這樣syslog程序就可 以通過讀取該緩衝區來獲取內核信息。printk()的用法很像printf(): 

printk("Hello world!A string:%s and an integer:%d\n",a_string,an_integer); 

printk()和printf()之間的一個顯著區別在於printk()允許通過指定一個標誌來設置優先級。syslog會根據這個優先級標 志來決定在什麼地方顯示這條系統信息。下面是一個使用這種優先級標誌的例子: 

printk(KERN_ERR "this is an error!\n");


printk()函數是直接使用了向終端寫函數tty_write()。而printf()函數是調用write()系統調用函數向標準輸出設備寫。所以 在用戶態(如進程0)不能夠直接使用printk()函數,而在內核態由於他已是特權級,所以無需系統調用來改變特權級,因而能夠直接使用 printk()函數。

printf是使用了標準的C庫函數的時候才能使用的,而內核中無法使用標準的C庫函數,所以就連最常見的printf都不能使用。


例如子printk函數的字符串參數中使用了KERN_ALERT,它實際上擴展爲字符串:“<1>”,而這部分信息沒有輸出到終端。實際上,這部分是內核信息的日誌級別,只有超過了當前日誌級別的信息纔會輸出到終端。當前內核的日誌級別可以在/proc/sys/kernel/printk文件中看到。這個文件包含了四個整數,其中前兩個是控制檯的當前日誌級別和默認日誌級別。我們在printk的參數中使用較高的日誌級別就是要保證信息得到輸出。在<linux/kernel.h>頭文件裏一共定義了8個級別(0-7)的輸出,從高到低分別由如下常量表示:

KERN_EMERG         :    最高級別,一般只用來打印崩潰信息

KERN_ALERT         :    需要立即處理的信息

KERN_CRIT          :    關鍵信息,一般用來顯示嚴重的硬件和軟件錯誤

KERN_ERR           :    用來顯示硬件錯誤

KERN_WARNING       :    顯示不會造成嚴重錯誤的警告信息

KERN_NOTICE        :    顯示需要引起注意的信息

KERN_INFO          :  顯示一般信息,例如驅動所發現的硬件列表

KERN_DEBUG    :  用來顯示調試信息


printk與printf的一個區別printk是“行驅動”的,也就是說只有收到一個換行符數據纔會真正輸出到終端,否則就不會有任何信息輸出。

另一個值得注意的問題是我們在調試嵌入式設備的時候,經常是從串口獲得顯示信息,如果我們使用printk過於頻繁的話,串口的傳輸速度就會成爲瓶頸,這樣會造成系統的性能下降甚至停止反應。   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章