《Linux核心設計與實現》第十八章讀書筆記

2022-08-17 17:18:17 字數 3057 閱讀 1525

需要:

1.乙個bug。

2.乙個藏匿bug的核心版本。

3.相關核心**的知識和運氣。

在使用者級的程式裡,bug常常表現得很直截了當;但在核心中卻不那麼清晰。

核心中bug多種多樣,不僅產生原因千奇百怪,表象也變化多端。如:

從隱藏在源**中的錯誤到展現出來的bug,往往是經歷一系列連鎖反應的時間才可能觸發的。

核心除錯有一些需要考慮的獨特問題,像定時限制和競爭條件,它們都是允許多個執行緒在核心中同時執行產生的結果。

核心列印函式printk()和c庫的printf()功能幾乎相同。printk()就是核心的格式化列印函式,但還有一些特殊功能:

彈性極佳,隨時可以被呼叫。但終端還沒有初始化之前,在某些地方不能使用printk()。

所以,除非在啟動過程的初期就要在終端上輸出,否則可以認為printk()在什麼情況下都能工作。

printk()可以指定乙個日誌級別。核心根據這個級別來判斷是否在終端上列印訊息。核心把級別比某個特定值低的所有訊息顯示在終端上。

指定乙個記錄級別:

printk(kern_warning 「this is a warning!\n」);

printk(kern_debug 「this is a debug notice!\n」);

printk(「i did not specify a loglevel!\n」);

解釋:kern_warning和kern_debug都是中的簡單巨集定義。它們擴充套件開是像「<4>」或「<7>」這樣的字串,加進printk()函式要列印的訊息的開頭。核心用這個指定的記錄等級和當前終端的記錄等級console_loglevel來決定是不是向終端上列印。

核心訊息都被儲存在乙個log_buf_len大小的環形佇列中。該緩衝區大小可以在編譯時通過設定config_log_buf_shift進行調整。核心在同一時間只能儲存16kb的核心訊息 。若已達最大值,再有pringk()呼叫時,新訊息會覆蓋老訊息。

(1)同時讀寫環形緩衝區,同步問題容易解決。在中斷上下文中也可以方便地使用printk()。

(2)記錄和維護更容易。大量的訊息同時產生,新訊息會覆蓋掉老訊息。

標準的linux系統上,使用者空間的守護程序klogd從記錄緩衝區中獲取核心訊息,在通過syslogd守護程序將它們儲存在系統日誌檔案中。klogd程式既可以從/proc/kmsg檔案中(預設方式),也可以通過syslog()系統呼叫讀取這些訊息。

klogd會阻塞,直到有新的核心訊息可供讀出。在被喚醒後,讀取出新的核心訊息並進行處理。預設情況下,它就是把訊息傳給syslog守護程序。

syslog守護程序把它接收到的所有訊息新增到乙個檔案中(預設為/war/log/messages,也可通過/etc/syslog.conf配置檔案重新指定)。

在啟動klpgd時,可通過指定-c標誌來改變終端的記錄等級。

慢慢養成順手寫printk()的習慣。

(1) kallsyms特性可以通過定義config_kallsyms配置選項(存放函式名稱和所有的符號名稱)啟用。該選項存放著核心映象中相應函式位址的符號名稱,所以核心可以列印解碼好的跟蹤線索。

(2) config_kallsyms_extra-pass選項會引起核心構建過程中再次忽略核心的目標**。這個選項只有在除錯kallsyms本身時才會有用。

配置選項都在核心配置編輯器的核心開發選單項中,都依賴於config_debug_kernel。

有用的選項:

slab layer debugging(slab層除錯選項)

high-memory debugging(高階記憶體除錯選項)

spin-lock debugging(自旋鎖除錯選項)

stack-overflaw checking(棧溢位檢查選項)

sleep-inside-spinlock checking(自旋鎖內睡眠選項)《最有用》

核心提供原子操作計數器。可以被配製成一旦在原子操作過程中程序進入睡眠或者做了一些可能引起睡眠的操作,就列印警告資訊並提供追蹤線索。這種除錯方法可以捕獲大量bug。

kgdb是乙個補丁,可以在遠端主機上通過串列埠利用gdb的所有功能對核心進行除錯。該補丁會在documentation/目錄下安裝很多說明檔案。需要兩台計算機:第一台執行帶有kgdb補丁的核心,第二胎通過序列線使用gdb對第一台進行除錯。

一般情況下,只要保留原有的演算法把新演算法加入到其他位置上,就能保證安全。可利用使用者id(uid)作為選擇條件實現:

if (current ->uid !=7777) else
解釋:除了uid為7777外其他所有的使用者都用的是老演算法。可以建立乙個uid為7777的永固專門用來測試新演算法。

**與程序無關或需要乙個針對所有情況都能使用的機制來控制某個特性,可以使用條件變數。只需要建立乙個全域性變數作為乙個條件選擇開關。若變數為0,就使用乙個分支上的**;如果不為0,就選擇另乙個分支。可以通過某種介面或偵錯程式對這個變數操控。

通過建立統計量並提供某種機制訪問其統計結果,可以滿足:掌握某個特定事件的發生規律;比較多個事件並從得出規律。

為了防止系統太過繁忙,兩種技巧:

(1) 重複頻率限制

(2) 發生次數限制

一開始需要乙個可靠的可複製的錯誤。接下來,需要乙個確保沒問題的核心和乙個肯定有問題的核心。然後在問題核心和良好內涵之間使用二分法,重複篩選直至侷限在兩個相繼發行的版本之間,從而容易定位。

我們可以在核心開發社群中尋求其他開發者的幫助。以後會重點推薦社群和最重要的論壇——linux核心郵件列表(lkml)。

除錯過程其實是乙個漫長又複雜的過程,是一種尋求實現與目標偏差的行為。從核心內建的除錯架構到除錯程式,從記錄日至盜用git二分法查詢等。感覺會困難重重,與除錯使用者程式完全不一樣。通過這章學習,我現在也只是了解了一些皮毛,還應該再加以深入理解並多加嘗試,慢慢體會。

linux第十八dd命令

指定大小的塊拷貝乙個檔案,並在拷貝的同時進行指定的轉換 類似於cp命令 cp etc fstab mnt fstab 要是使用dd命令是怎麼做呢?dd if etc fstab of mnt fstab 可以完成的將改檔案拷貝到 mnt fstab if 引數代表的是資料來源 of引數代表的是資料儲...

逆向工程核心原理 第十八章

我們使用add.exe檔案 我們將add.exe檔案拖入upack加殼工具,這裡的版本是0.39final,lc選擇6 點選確定後得到add.exe.bak的檔案,我們去掉.bak後就可以直接使用了,這裡為了區分,我將加殼後的檔案取名為add upack 6.exe。首先我們先使用hex瀏覽器檢視加...

第十八章 發布與訂閱

通過subscribe命令,客戶端可以訂閱乙個或多個頻道,每當有其他客戶端向被訂閱的頻道傳送訊息,頻道的訂閱者都會收到訊息 通過psubscribe命令,客戶端可以訂閱乙個或多個模式,每當有其他客戶端向被訂閱的頻道傳送訊息,與該頻道相匹配的模式訂閱者也會收到 redisserver中用乙個字典儲存了...