偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

ftrace:跟蹤你的內(nèi)核函數(shù)!

系統(tǒng) Linux
ftrace 是一個(gè) Linux 內(nèi)核特性,它可以讓你去跟蹤 Linux 內(nèi)核的函數(shù)調(diào)用。為什么要這么做呢?好吧,假設(shè)你調(diào)試一個(gè)奇怪的問(wèn)題,而你已經(jīng)得到了你的內(nèi)核版本中這個(gè)問(wèn)題在源代碼中的開(kāi)始的位置,而你想知道這里到底發(fā)生了什么?

[[218222]]

大家好!今天我們將去討論一個(gè)調(diào)試工具:ftrace,之前我的博客上還沒(méi)有討論過(guò)它。還有什么能比一個(gè)新的調(diào)試工具更讓人激動(dòng)呢?

這個(gè)非常棒的 ftrace 并不是個(gè)新的工具!它大約在 Linux 的 2.6 內(nèi)核版本中就有了,時(shí)間大約是在 2008 年。這一篇是我用谷歌能找到的最早的文檔。因此,如果你是一個(gè)調(diào)試系統(tǒng)的“老手”,可能早就已經(jīng)使用它了!

我知道,ftrace 已經(jīng)存在了大約 2.5 年了(LCTT 譯注:距本文初次寫(xiě)作時(shí)),但是還沒(méi)有真正的去學(xué)習(xí)它。假設(shè)我明天要召開(kāi)一個(gè)專題研究會(huì),那么,關(guān)于 ftrace 應(yīng)該討論些什么?因此,今天是時(shí)間去討論一下它了!

 

什么是 ftrace?

ftrace 是一個(gè) Linux 內(nèi)核特性,它可以讓你去跟蹤 Linux 內(nèi)核的函數(shù)調(diào)用。為什么要這么做呢?好吧,假設(shè)你調(diào)試一個(gè)奇怪的問(wèn)題,而你已經(jīng)得到了你的內(nèi)核版本中這個(gè)問(wèn)題在源代碼中的開(kāi)始的位置,而你想知道這里到底發(fā)生了什么?

每次在調(diào)試的時(shí)候,我并不會(huì)經(jīng)常去讀內(nèi)核源代碼,但是,極個(gè)別的情況下會(huì)去讀它!例如,本周在工作中,我有一個(gè)程序在內(nèi)核中卡死了。查看到底是調(diào)用了什么函數(shù),能夠幫我更好的理解在內(nèi)核中發(fā)生了什么,哪些系統(tǒng)涉及其中?。ㄔ谖业哪莻€(gè)案例中,它是虛擬內(nèi)存系統(tǒng))。

我認(rèn)為 ftrace 是一個(gè)十分好用的工具(它肯定沒(méi)有 strace 那樣使用廣泛,也比它難以使用),但是它還是值得你去學(xué)習(xí)。因此,讓我們開(kāi)始吧!

 

使用 ftrace 的***步

不像 straceperf,ftrace 并不是真正的 程序 – 你不能只運(yùn)行 ftrace my_cool_function。那樣太容易了!

如果你去讀 使用 ftrace 調(diào)試內(nèi)核,它會(huì)告訴你從 cd /sys/kernel/debug/tracing 開(kāi)始,然后做很多文件系統(tǒng)的操作。

對(duì)于我來(lái)說(shuō),這種辦法太麻煩——一個(gè)使用 ftrace 的簡(jiǎn)單例子像是這樣:

  1. cd /sys/kernel/debug/tracing
  2. echo function > current_tracer
  3. echo do_page_fault > set_ftrace_filter
  4. cat trace

這個(gè)文件系統(tǒng)是跟蹤系統(tǒng)的接口(“給這些神奇的文件賦值,然后該發(fā)生的事情就會(huì)發(fā)生”)理論上看起來(lái)似乎可用,但是它不是我的***方式。

幸運(yùn)的是,ftrace 團(tuán)隊(duì)也考慮到這個(gè)并不友好的用戶界面,因此,它有了一個(gè)更易于使用的界面,它就是 trace-cmd?。?!trace-cmd 是一個(gè)帶命令行參數(shù)的普通程序。我們后面將使用它!我在 LWN 上找到了一個(gè) trace-cmd 的使用介紹:trace-cmd: Ftrace 的一個(gè)前端。

 

開(kāi)始使用 trace-cmd:讓我們僅跟蹤一個(gè)函數(shù)

首先,我需要去使用 sudo apt-get install trace-cmd 安裝 trace-cmd,這一步很容易。

對(duì)于***個(gè) ftrace 的演示,我決定去了解我的內(nèi)核如何去處理一個(gè)頁(yè)面故障。當(dāng) Linux 分配內(nèi)存時(shí),它經(jīng)常偷懶,(“你并不是真的計(jì)劃去使用內(nèi)存,對(duì)嗎?”)。這意味著,當(dāng)一個(gè)應(yīng)用程序嘗試去對(duì)分配給它的內(nèi)存進(jìn)行寫(xiě)入時(shí),就會(huì)發(fā)生一個(gè)頁(yè)面故障,而這個(gè)時(shí)候,內(nèi)核才會(huì)真正的為應(yīng)用程序去分配物理內(nèi)存。

我們開(kāi)始使用 trace-cmd 并讓它跟蹤 do_page_fault 函數(shù)!

  1. $ sudo trace-cmd record -p function -l do_page_fault
  2. plugin 'function'
  3. Hit Ctrl^C to stop recording

我將它運(yùn)行了幾秒鐘,然后按下了 Ctrl+C。 讓我大吃一驚的是,它竟然產(chǎn)生了一個(gè) 2.5MB 大小的名為 trace.dat 的跟蹤文件。我們來(lái)看一下這個(gè)文件的內(nèi)容!

  1. $ sudo trace-cmd report
  2. chrome-15144 [000] 11446.466121: function: do_page_fault
  3. chrome-15144 [000] 11446.467910: function: do_page_fault
  4. chrome-15144 [000] 11446.469174: function: do_page_fault
  5. chrome-15144 [000] 11446.474225: function: do_page_fault
  6. chrome-15144 [000] 11446.474386: function: do_page_fault
  7. chrome-15144 [000] 11446.478768: function: do_page_fault
  8. CompositorTileW-15154 [001] 11446.480172: function: do_page_fault
  9. chrome-1830 [003] 11446.486696: function: do_page_fault
  10. CompositorTileW-15154 [001] 11446.488983: function: do_page_fault
  11. CompositorTileW-15154 [001] 11446.489034: function: do_page_fault
  12. CompositorTileW-15154 [001] 11446.489045: function: do_page_fault
  13.  

看起來(lái)很整潔 – 它展示了進(jìn)程名(chrome)、進(jìn)程 ID(15144)、CPU ID(000),以及它跟蹤的函數(shù)。

通過(guò)察看整個(gè)文件,(sudo trace-cmd report | grep chrome)可以看到,我們跟蹤了大約 1.5 秒,在這 1.5 秒的時(shí)間段內(nèi),Chrome 發(fā)生了大約 500 個(gè)頁(yè)面故障。真是太酷了!這就是我們做的***個(gè) ftrace!

 

下一個(gè) ftrace 技巧:我們來(lái)跟蹤一個(gè)進(jìn)程!

好吧,只看一個(gè)函數(shù)是有點(diǎn)無(wú)聊!假如我想知道一個(gè)程序中都發(fā)生了什么事情。我使用一個(gè)名為 Hugo 的靜態(tài)站點(diǎn)生成器??纯磧?nèi)核為 Hugo 都做了些什么事情?

在我的電腦上 Hugo 的 PID 現(xiàn)在是 25314,因此,我使用如下的命令去記錄所有的內(nèi)核函數(shù):

  1. sudo trace-cmd record --help # I read the help!
  2. sudo trace-cmd record -p function -P 25314 # record for PID 25314

sudo trace-cmd report 輸出了 18,000 行。如果你對(duì)這些感興趣,你可以看 這里是所有的 18,000 行的輸出。

18,000 行太多了,因此,在這里僅摘錄其中幾行。

當(dāng)系統(tǒng)調(diào)用 clock_gettime 運(yùn)行的時(shí)候,都發(fā)生了什么:

  1. compat_SyS_clock_gettime
  2. SyS_clock_gettime
  3. clockid_to_kclock
  4. posix_clock_realtime_get
  5. getnstimeofday64
  6. __getnstimeofday64
  7. arch_counter_read
  8. __compat_put_timespec

這是與進(jìn)程調(diào)試相關(guān)的一些東西:

  1. cpufreq_sched_irq_work
  2. wake_up_process
  3. try_to_wake_up
  4. _raw_spin_lock_irqsave
  5. do_raw_spin_lock
  6. _raw_spin_lock
  7. do_raw_spin_lock
  8. walt_ktime_clock
  9. ktime_get
  10. arch_counter_read
  11. walt_update_task_ravg
  12. exiting_task
  13.  

雖然你可能還不理解它們是做什么的,但是,能夠看到所有的這些函數(shù)調(diào)用也是件很酷的事情。

“function graph” 跟蹤

這里有另外一個(gè)模式,稱為 function_graph。除了它既可以進(jìn)入也可以退出一個(gè)函數(shù)外,其它的功能和函數(shù)跟蹤器是一樣的。這里是那個(gè)跟蹤器的輸出

  1. sudo trace-cmd record -p function_graph -P 25314

同樣,這里只是一個(gè)片斷(這次來(lái)自 futex 代碼):

  1. | futex_wake() {
  2. | get_futex_key() {
  3. | get_user_pages_fast() {
  4. 1.458 us | __get_user_pages_fast();
  5. 4.375 us | }
  6. | __might_sleep() {
  7. 0.292 us | ___might_sleep();
  8. 2.333 us | }
  9. 0.584 us | get_futex_key_refs();
  10. | unlock_page() {
  11. 0.291 us | page_waitqueue();
  12. 0.583 us | __wake_up_bit();
  13. 5.250 us | }
  14. 0.583 us | put_page();
  15. + 24.208 us | }

我們看到在這個(gè)示例中,在 futex_wake 后面調(diào)用了 get_futex_key。這是在源代碼中真實(shí)發(fā)生的事情嗎?我們可以檢查一下??!這里是在 Linux 4.4 中 futex_wake 的定義 (我的內(nèi)核版本是 4.4)。

為節(jié)省時(shí)間我直接貼出來(lái),它的內(nèi)容如下:

  1. static int
  2. futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
  3. {
  4. struct futex_hash_bucket *hb;
  5. struct futex_q *this, *next;
  6. union futex_key key = FUTEX_KEY_INIT;
  7. int ret;
  8. WAKE_Q(wake_q);
  9.  
  10. if (!bitset)
  11. return -EINVAL;
  12.  
  13. ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_READ);

如你所見(jiàn),在 futex_wake 中的***個(gè)函數(shù)調(diào)用真的是 get_futex_key! 太棒了!相比閱讀內(nèi)核代碼,閱讀函數(shù)跟蹤肯定是更容易的找到結(jié)果的辦法,并且讓人高興的是,還能看到所有的函數(shù)用了多長(zhǎng)時(shí)間。

 

如何知道哪些函數(shù)可以被跟蹤

如果你去運(yùn)行 sudo trace-cmd list -f,你將得到一個(gè)你可以跟蹤的函數(shù)的列表。它很簡(jiǎn)單但是也很重要。

 

***一件事:事件!

現(xiàn)在,我們已經(jīng)知道了怎么去跟蹤內(nèi)核中的函數(shù),真是太酷了!

還有一類我們可以跟蹤的東西!有些事件與我們的函數(shù)調(diào)用并不相符。例如,你可能想知道當(dāng)一個(gè)程序被調(diào)度進(jìn)入或者離開(kāi) CPU 時(shí),都發(fā)生了什么事件!你可能想通過(guò)“盯著”函數(shù)調(diào)用計(jì)算出來(lái),但是,我告訴你,不可行!

由于函數(shù)也為你提供了幾種事件,因此,你可以看到當(dāng)重要的事件發(fā)生時(shí),都發(fā)生了什么事情。你可以使用 sudo cat /sys/kernel/debug/tracing/available_events 來(lái)查看這些事件的一個(gè)列表。 

我查看了全部的 schedswitch 事件。我并不完全知道 schedswitch 是什么,但是,我猜測(cè)它與調(diào)度有關(guān)。

  1. sudo cat /sys/kernel/debug/tracing/available_events
  2. sudo trace-cmd record -e sched:sched_switch
  3. sudo trace-cmd report

輸出如下:

  1. 16169.624862: Chrome_ChildIOT:24817 [112] S ==> chrome:15144 [120]
  2. 16169.624992: chrome:15144 [120] S ==> swapper/3:0 [120]
  3. 16169.625202: swapper/3:0 [120] R ==> Chrome_ChildIOT:24817 [112]
  4. 16169.625251: Chrome_ChildIOT:24817 [112] R ==> chrome:1561 [112]
  5. 16169.625437: chrome:1561 [112] S ==> chrome:15144 [120]
  6.  

現(xiàn)在,可以很清楚地看到這些切換,從 PID 24817 -> 15144 -> kernel -> 24817 -> 1561 -> 15114。(所有的這些事件都發(fā)生在同一個(gè) CPU 上)。

 

ftrace 是如何工作的?

ftrace 是一個(gè)動(dòng)態(tài)跟蹤系統(tǒng)。當(dāng)我們開(kāi)始 ftrace 內(nèi)核函數(shù)時(shí),函數(shù)的代碼會(huì)被改變。讓我們假設(shè)去跟蹤 do_page_fault 函數(shù)。內(nèi)核將在那個(gè)函數(shù)的匯編代碼中插入一些額外的指令,以便每次該函數(shù)被調(diào)用時(shí)去提示跟蹤系統(tǒng)。內(nèi)核之所以能夠添加額外的指令的原因是,Linux 將額外的幾個(gè) NOP 指令編譯進(jìn)每個(gè)函數(shù)中,因此,當(dāng)需要的時(shí)候,這里有添加跟蹤代碼的地方。

這是一個(gè)十分復(fù)雜的問(wèn)題,因?yàn)椋?dāng)不需要使用 ftrace 去跟蹤我的內(nèi)核時(shí),它根本就不影響性能。而當(dāng)我需要跟蹤時(shí),跟蹤的函數(shù)越多,產(chǎn)生的開(kāi)銷(xiāo)就越大。

(或許有些是不對(duì)的,但是,我認(rèn)為的 ftrace 就是這樣工作的)

 

更容易地使用 ftrace:brendan gregg 的工具及 kernelshark

正如我們?cè)谖募兴懻摰?,你需要去考慮很多的關(guān)于單個(gè)的內(nèi)核函數(shù)/事件直接使用 ftrace 都做了些什么。能夠做到這一點(diǎn)很酷!但是也需要做大量的工作!

Brendan Gregg (我們的 Linux 調(diào)試工具“大神”)有個(gè)工具倉(cāng)庫(kù),它使用 ftrace 去提供關(guān)于像 I/O 延遲這樣的各種事情的信息。這是它在 GitHub 上全部的 perf-tools 倉(cāng)庫(kù)。

這里有一個(gè)權(quán)衡,那就是這些工具易于使用,但是你被限制僅能用于 Brendan Gregg 認(rèn)可并做到工具里面的方面。它包括了很多方面!:)

另一個(gè)工具是將 ftrace 的輸出可視化,做的比較好的是 kernelshark。我還沒(méi)有用過(guò)它,但是看起來(lái)似乎很有用。你可以使用 sudo apt-get install kernelshark 來(lái)安裝它。

 

一個(gè)新的超能力

我很高興能夠花一些時(shí)間去學(xué)習(xí) ftrace!對(duì)于任何內(nèi)核工具,不同的內(nèi)核版本有不同的功效,我希望有一天你能發(fā)現(xiàn)它很有用!

 

ftrace 系列文章的一個(gè)索引

***,這里是我找到的一些 ftrace 方面的文章。它們大部分在 LWN (Linux 新聞周刊)上,它是 Linux 的一個(gè)極好的資源(你可以購(gòu)買(mǎi)一個(gè) 訂閱?。?/p>

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2021-09-06 07:45:08

LinuxLinux內(nèi)核

2025-04-01 02:00:22

2022-04-12 08:22:54

Linux內(nèi)核操作系統(tǒng)

2022-10-30 10:31:42

i2ccpuftrace

2022-06-28 13:43:48

瀏覽器Chrome

2021-12-09 08:09:31

Linux內(nèi)核臟頁(yè)

2021-02-25 09:50:01

LinuxWindows內(nèi)核

2017-01-16 15:20:03

Linux內(nèi)核Oops

2022-04-29 09:00:00

Platform架構(gòu)內(nèi)核線程

2018-05-14 09:48:45

Linux內(nèi)核模塊Kgotobed

2011-04-25 16:35:06

Linux調(diào)用

2022-08-15 15:19:42

黑客漏洞智能手機(jī)

2015-09-11 15:56:52

內(nèi)核構(gòu)建Linux

2012-04-09 14:51:31

2023-10-26 11:39:54

Linux系統(tǒng)CPU

2021-10-06 09:46:17

trace-cmd追蹤內(nèi)核Linux

2021-08-27 17:00:51

Linux內(nèi)核

2020-06-10 16:10:35

ActivityWat屏幕使用時(shí)間Linux

2020-03-04 12:55:13

Emacs待辦事項(xiàng)應(yīng)用

2023-11-30 07:37:49

MySQL函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)