国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Linux內(nèi)核調(diào)試利器kprobe的使用,從這幾點入手!

2022-04-28 16:20 作者:補給站Linux內(nèi)核  | 我要投稿
  • 軟件調(diào)試 是軟件開發(fā)中一個必不可少的過程,通過軟件調(diào)試可以排查系統(tǒng)中存在的 BUG。我們在開發(fā)應(yīng)用層程序時,可以使用 GDB 對程序進行調(diào)試。但由于 GDB 只能調(diào)試應(yīng)用層程序,并不能用于調(diào)試內(nèi)核代碼。

  • 那么,如何調(diào)試內(nèi)核代碼呢?與調(diào)試應(yīng)用層程序的 GDB 類似,調(diào)試內(nèi)核代碼也有個名叫 KGDB 的工具,但是使用起來比較繁瑣。所以,本文將會介紹一個使用起來比較簡單的內(nèi)核調(diào)試工具:kprobe。

kprobe 簡介

  • 回憶一下我們在開發(fā)應(yīng)用程序時是怎樣調(diào)試代碼的?最原始的方法就是,在代碼中使用 printf 這類打印函數(shù)把結(jié)果輸出到屏幕或者日志中。當然在內(nèi)核中有類似的打印函數(shù):printk,但使用 printk 函數(shù)調(diào)試內(nèi)核代碼的話,必須要重新編譯 Linux 內(nèi)核代碼,代價非常高。

  • 所以,內(nèi)核開發(fā)者們開發(fā)出一種不需要重新編譯內(nèi)核代碼的調(diào)試工具:kprobe。

  • kprobe 可以讓用戶在內(nèi)核幾乎所有的地址空間或函數(shù)(某些函數(shù)是被能被探測的)中插入探測點,用戶可以在這些探測點上通過定義自定義函數(shù)來調(diào)試內(nèi)核代碼。

  • 用戶可以對一個探測點進行執(zhí)行前和執(zhí)行后調(diào)試,在介紹 kprobe 的使用方式前,我們先來了解一下 struct kprobe 結(jié)構(gòu),其定義如下:

  • 一個 struct kprobe 結(jié)構(gòu)表示一個探測點,下面介紹一下其各個字段的作用:

  1. addr:要探測的指令所在的內(nèi)存地址(由于需要知道指令的內(nèi)存地址,所以比較少使用)。

  2. symbol_name:要探測的內(nèi)核函數(shù),symbol_name 與 addr 只能選擇一個進行探測。

  3. offset:探測點在內(nèi)核函數(shù)內(nèi)的偏移量,用于探測內(nèi)核函數(shù)內(nèi)部的指令,如果該值為0表示函數(shù)的入口。

  4. pre_handler:在探測點處的指令執(zhí)行前,被調(diào)用的調(diào)試函數(shù)。

  5. post_handler:在探測點處的指令執(zhí)行后,被調(diào)用的調(diào)試函數(shù)。

  6. fault_handler:在執(zhí)行 pre_handler、post_handler 或單步執(zhí)行被探測指令時出現(xiàn)內(nèi)存異常,則會調(diào)用這個回調(diào)函數(shù)。

  • 一個 kprobe 探測點的執(zhí)行過程如下圖所示:


  • 從上面的介紹可知,kprobe 一般用于調(diào)試內(nèi)核函數(shù)。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。∏?00名進群領(lǐng)取,額外贈送一份價值699的內(nèi)核資料包(含視頻教程、電子書、實戰(zhàn)項目及代碼)?


kprobe 使用

  • 接下來,我們介紹一下怎么使用 kprobe 來調(diào)試內(nèi)核函數(shù)。

  • 使用 kprobe 來進行內(nèi)核調(diào)試的方式有兩種:

  1. 第一種是通過編寫內(nèi)核模塊,向內(nèi)核注冊探測點。探測函數(shù)可根據(jù)需要自行定制,使用靈活方便;

  2. 第二種方式是使用 kprobes on ftrace,這種方式是 kprobe 和 ftrace 結(jié)合使用,即可以通過 kprobe 來優(yōu)化 ftrace 來跟蹤函數(shù)的調(diào)用。

  • 由于第一種方式靈活而且功能更為強大,所以本文主要介紹第一種使用方式。

  • 要編寫一個 kprobe 內(nèi)核模塊,可以按照以下步驟完成:

  1. 第一步:根據(jù)需要來編寫探測函數(shù),如 pre_handler 和 post_handler 回調(diào)函數(shù)。

  2. 第二步:定義 struct kprobe 結(jié)構(gòu)并且填充其各個字段,如要探測的內(nèi)核函數(shù)名和各個探測回調(diào)函數(shù)。

  3. 第三步:通過調(diào)用 register_kprobe 函數(shù)注冊一個探測點。

  4. 第四步:編寫 Makefile 文件。

  5. 第五步:編譯并安裝內(nèi)核模塊。

  • 接下來就按照上面的步驟來完成一個 kprobe 的內(nèi)核模塊。

1. 定義回調(diào)函數(shù)

  • 第一步就是編寫追蹤的回調(diào)函數(shù),一般來說只需要編寫 pre_handler、post_handler 和 fault_handler 這三個回調(diào)函數(shù),當然也可以只編寫你想追蹤的其中某一個回調(diào)函數(shù)。下面我們將會完成這三個追蹤回調(diào)函數(shù)的編寫:

pre_handler 回調(diào)函數(shù)

  • 我們首先編寫要追蹤的內(nèi)核函數(shù)被調(diào)用前的回調(diào)函數(shù) pre_handler,代碼如下:

static int pre_handler(struct kprobe *p, struct pt_regs *regs) { ? ?printk(KERN_INFO "pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx\n", ? ? ? ? ? p->addr, regs->ip, regs->flags); ? ?return 0; }

上面的函數(shù)只是簡單的打印了要追蹤的內(nèi)核函數(shù)的內(nèi)存地址、ip 寄存器和 flags 寄存器的值,在函數(shù)的定義中可以發(fā)現(xiàn)有個類型為 pt_regs 結(jié)構(gòu)的參數(shù) ,其主要保存了 CPU 各個寄存器的值,不同 CPU 架構(gòu)的定義不一樣,例如 x86 CPU 架構(gòu)的定義如下:

  • 所以我們可以通過這個結(jié)構(gòu)來獲取 CPU 各個寄存器的值。

post_handler 回調(diào)函數(shù)

  • 接著我們來編寫要追蹤的內(nèi)核函數(shù)被調(diào)用后的回調(diào)函數(shù) post_handler,其代碼如下:

  • post_handler 回調(diào)函數(shù)也只是簡單的打印了要追蹤的內(nèi)核函數(shù)的內(nèi)存地址和 flags 寄存器的值。

fault_handler 回調(diào)函數(shù)

  • 最后我們來編寫當發(fā)生內(nèi)存異常時的回調(diào)函數(shù) fault_handler,其代碼如下:

  • fault_handler 回調(diào)函數(shù)打印了要追蹤的內(nèi)核函數(shù)的內(nèi)存地址和發(fā)生異常時的異常編號。

2. 定義 kprobe 結(jié)構(gòu)

  • 接下來我們定義一個 struct kprobe 結(jié)構(gòu)并且填充其各個字段值,代碼如下:

  • 由于我們要追蹤 do_fork 內(nèi)核函數(shù),所以在 kprobe 結(jié)構(gòu)的 symbol_name 設(shè)置為 do_fork 字符串,然后設(shè)置各個回調(diào)函數(shù)即可。

3. 注冊追蹤點

  • 最后通過調(diào)用 register_kprobe 函數(shù)來注冊追蹤點,代碼如下:

編寫 Makefile 文件

  • Makefile 文件用于編譯內(nèi)核模塊時使用,一般來說編譯內(nèi)核模塊的 Makefile 格式相對固定,如下:


5. 編譯并安裝內(nèi)核模塊

  • 最后,我們編譯并且安裝這個內(nèi)核模塊,命令如下:

安裝完成后,隨便敲入一個命令(如 ls),然后通過調(diào)用 dmesg 命令查看內(nèi)核模塊輸出的結(jié)果,如下所示:

  • 可以看出,我們的調(diào)試模塊已經(jīng)正常工作,并且輸出我們需要的信息。

總結(jié)

  • 本文主要介紹了 kprobe 的使用方式,kprobe 的功能非常強大,可以幫助我們發(fā)現(xiàn)內(nèi)核的一些 BUG。當然,本文也只是非常簡單的介紹其使用,但有了這些基礎(chǔ)就可以完成很多復雜的調(diào)試。


Linux內(nèi)核調(diào)試利器kprobe的使用,從這幾點入手!的評論 (共 條)

分享到微博請遵守國家法律
定西市| 鹤庆县| 象州县| 涪陵区| 临桂县| 台湾省| 金秀| 且末县| 祁连县| 思南县| 泗阳县| 阳春市| 长沙市| 宜宾市| 中宁县| 弥勒县| 临江市| 乐亭县| 汉寿县| 敦煌市| 博客| 邵东县| 罗江县| 泉州市| 广元市| 正定县| 如皋市| 新泰市| 客服| 麻城市| 秀山| 巩义市| 上饶市| 海宁市| 高阳县| 宾川县| 神农架林区| 富顺县| 防城港市| 象山县| 洛扎县|