自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux內核輸出的日志去哪里了

系統(tǒng) Linux
那當我們調用printk函數(shù)后,這些輸出的信息到哪里去了呢?我們又如何在linux下的用戶態(tài),查看這些信息呢?

[[422485]]

因為圖片比較大,微信公眾號上壓縮的比較厲害,所以很多細節(jié)都看不清了,我單獨傳了一份到github上,想要原版圖片的,可以點擊下方的閱讀原文,或者直接使用下面的鏈接,來訪問github:

https://github.com/wangyuntao/linux-kernel-illustrated

另外,精致全景圖系列文章,以及之后的linux內核分析文章,我都會整理到這個github倉庫里,歡迎大家star收藏。

熟悉linux內核,或者看過linux內核源碼的同學就會知道,在內核中,有一個類似于c語言的輸出函數(shù),叫做printk,使用它,我們可以打印各種我們想要的信息,比如內核當前的運行狀態(tài),又或者是我們自己的調試日志等,非常方便。

那當我們調用printk函數(shù)后,這些輸出的信息到哪里去了呢?我們又如何在linux下的用戶態(tài),查看這些信息呢?

為了解答這些疑問,我畫了一張printk全景圖,放在了文章開始的部分,這張圖既包含了printk在內核態(tài)的實現(xiàn),又包含了其輸出的信息在用戶態(tài)如何查看。

我們可以根據(jù)這張圖,來理解printk的整體架構。

在內核編碼時,如果想要輸出一些信息,通常并不會直接使用printk,而是會使用其衍生函數(shù),比如 pr_err / pr_info / pr_debug 等,這些衍生函數(shù)附帶了日志級別、所屬模塊等其他信息,比較友好,但其最終還是調用了printk。

printk函數(shù)會將每次輸出的日志,放到內核為其專門分配的名為ring buffer的一個槽位里。

ring buffer其實就是一個用數(shù)組實現(xiàn)的環(huán)形隊列,不過既然是環(huán)形隊列,就會有一個問題,即當ring buffer滿了的時候,下一條新的日志,會覆蓋最開始的舊的日志。

ring buffer的大小,可以通過內核參數(shù)來修改。

printk在將日志放到ring buffer后,會再調用系統(tǒng)console的相關方法,將還未輸出到系統(tǒng)控制臺的消息,繼續(xù)輸出到控制臺,這個后面會詳細說,這里就暫不贅述。

以上就是printk在內核態(tài)的實現(xiàn)。

在用戶態(tài),我們有幾個方式,可以查看printk輸出的內核日志,比如使用dmesg命令,cat /proc/kmsg文件,或者是使用klogctl函數(shù)等,這些方式分別對應于全景圖中用戶態(tài)的橙色、綠色、和藍色的部分。

dmesg命令,在默認情況下,是通過讀取/dev/kmsg文件,來實現(xiàn)查看內核日志的。

當該命令運行時,dmesg會先調用open函數(shù),打開/dev/kmsg文件,該打開操作在內核中的邏輯,會為dmesg分配一個file實例,在這個file實例里,會有一個seq變量,該變量記錄著下一條要讀取的內核日志在ring buffer中的位置。

剛打開/dev/kmsg文件時,這個seq指向的就是ring buffer中最開始的那條日志。

之后,dmesg會以打開的/dev/kmsg文件為媒介,不斷的調用read函數(shù),從內核中讀取日志消息,每讀取出一條,seq的值都會加一,即指向下一條日志的位置,依次往復,直到所有的內核日志讀取完畢,dmesg退出。

以上就是dmesg的主體實現(xiàn)。

第二種查看內核日志的方式,是通過 cat /proc/kmsg 命令。

該命令和dmesg命令的實現(xiàn)機制基本類似,都是通過讀文件,只不過cat讀取的是/proc/kmsg文件,而dmesg讀取的是/dev/kmsg文件。

讀取這兩個文件最大的區(qū)別是,/dev/kmsg文件每次打開時,內核都會為其分配一個單獨的seq變量,而/proc/kmsg文件每次打開時,用的都是同一個全局的靜態(tài)seq變量,叫做syslog_seq。

syslog_seq指向的也是下一條要讀取的內核日志在ring buffer中的位置,但因為它是一個全局的靜態(tài)變量,當有多個進程要讀取/proc/kmsg文件時,就會有一個比較嚴重的問題,即內核日志會被這幾個進程隨機搶占讀取,也就是說,每個進程讀到的都是整個內核日志的一部分,是不完整的,這也是dmesg命令默認不使用/proc/kmsg文件的原因。

第三種查看內核日志的方式,是通過klogctl函數(shù)。

該函數(shù)是glibc對syslog系統(tǒng)調用的一個簡單封裝,其具體使用方式,可以參考全景圖中用戶態(tài)的藍色部分。

klogctl函數(shù)可以指定很多命令,在上圖的示例中,我們使用的是SYSLOG_ACTION_READ命令,以此來模擬 cat /proc/kmsg 行為。

其實在內核層面,cat /proc/kmsg命令,使用的就是klogctl對應的syslog系統(tǒng)調用的SYSLOG_ACTION_READ命令的處理邏輯,所以示例中的klogctl函數(shù)相關代碼,和 cat /proc/kmsg 命令其實是等價的。

也就是說,klogctl函數(shù)在內核里使用的也是syslog_seq變量,它也有和/proc/kmsg文件同樣的問題。

其實還有一種方式可以查看內核日志,就是通過系統(tǒng)控制臺。

但這種方式和前面講的三種方式都不一樣,它是完全被動的,是內核在調用printk函數(shù),將日志信息放到ring buffer后,再去通知系統(tǒng)控制臺,告知其可以輸出這些日志。

系統(tǒng)控制臺也是通過一個console_seq變量,記錄下一條要輸出內核日志的所在位置。

這里說的系統(tǒng)控制臺,是指我們在開機的時候,黑色屏幕輸出的那些內容,但當我們進入圖形化界面后,我們就看不到系統(tǒng)控制臺的輸出了,除非我們再用 ctrl + alt + f1/f2/f3 等方式,切換成系統(tǒng)控制臺。

系統(tǒng)控制臺輸出的內容,是被日志級別過濾過的,內核默認的日志過濾級別是7,即debug級別以上的日志,比如info / err 等,這些都會輸出,但debug級別不會輸出。

該日志過濾級別,可以通過很多方式改變,比如說,可以通過內核參數(shù) loglevel,所以,如果發(fā)現(xiàn)系統(tǒng)控制臺沒有輸出想要的日志信息,先看下其是否被過濾掉了。

以上就是printk生態(tài)的完整實現(xiàn)。

了解printk函數(shù)的實現(xiàn),對于內核開發(fā)者或研究者來說,意義非常大,但對于普通的應用開發(fā)人員來說,又有什么幫助呢?

其實,隨著技術的深入,我們不應該再只關心應用層面的行為,而且還要關心系統(tǒng)層面的行為,這樣我們才能更好的去定位問題,更好的去保證我們應用的健康運行。

比如,當我們的應用需要內存時,會向操作系統(tǒng)申請,操作系統(tǒng)此時給我們的,其實是虛擬內存,只有當我們的進程真正的在使用這些內存時,比如讀/寫,操作系統(tǒng)才會為其分配物理內存。

但假設此時物理內存沒有了,那操作系統(tǒng)會怎么辦?

對于linux內核來說,它會選擇一個使用內存最多的進程,然后將其kill掉,以此來釋放內存,保證后續(xù)的內存分配操作能夠成功,這個我在之前文章 為什么我的進程被kill掉了 有詳細講過。

對于內核的這種行為,我們就應該多加關注,而關注的方式,就是查看內核日志。

比如,linux內核在kill掉進程時,會用pr_err記錄一行日志:

如果我們發(fā)現(xiàn)一個進程跑著跑著就沒有了,就可以通過dmesg命令,查看是否有這個日志,如果有,說明該進程因為系統(tǒng)內存不足,被操作系統(tǒng)kill掉了。

類似的,內核里還有很多error級別,甚至更高級別的日志需要我們關注,通過這些日志,我們可以及時的發(fā)現(xiàn)系統(tǒng)的異常情況,必要時可以人工介入進行干預。

總之,對系統(tǒng)了解的越深,內核日志對我們的幫助就越大。

就這些,希望你喜歡。

本文轉載自微信公眾號「卯時卯刻」,可以通過以下二維碼關注。轉載本文請聯(lián)系卯時卯刻公眾號。

 

責任編輯:武曉燕 來源: 卯時卯刻
相關推薦

2021-09-29 09:50:41

Linux內核日志

2017-10-12 10:06:23

Linux內存free命令

2011-10-14 10:27:04

OpenFlow

2022-11-27 11:00:15

2021-07-29 20:29:36

Linux c 代碼Java

2014-04-10 15:42:08

Linux系統(tǒng)內存

2021-02-25 09:50:01

LinuxWindows內核

2013-10-28 09:40:51

Android內核

2014-07-09 13:48:08

去IOE浪潮

2020-06-10 10:50:15

Linuxpstore內核

2010-10-25 10:52:34

2010-05-20 09:09:07

Linux內核

2013-11-07 13:59:56

Linux內核

2013-11-25 14:07:11

Linux內核內核特性

2013-11-05 09:58:39

Linux內核

2013-11-06 13:03:10

Linux內核

2013-11-12 11:01:46

Linux內核

2018-10-29 13:46:02

2021-11-17 10:25:28

loguru日志Python

2021-02-20 06:08:07

LinuxWindows內核
點贊
收藏

51CTO技術棧公眾號