日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux TraceEvent - 史上最長宏定義

Linux閱碼場 ? 來源:Linuxer ? 2020-06-28 09:34 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

TraceEvent是內(nèi)核中一種探測的機制,據(jù)說在不使能的時候是沒有損耗的。據(jù)說使用起來挺簡單,但是要看懂著實需要花些力氣。

例子

從例子中學(xué)習(xí),一般都是比較好的方法。內(nèi)核開發(fā)者也比較nice,在內(nèi)核源碼samples/trace_events目錄下就有這么一個例子。

其中文件一共有三個:

這個例子以內(nèi)核模塊的形式存在,所以只要執(zhí)行make就可以編譯完成。

總的來說,要定義和使用tracepoint,只要做兩點。

用TRACE_EVENT來定義一個新的tracepoint

在需要的地方,使用函數(shù)trace_XXX打印輸出

有了例子我們就要跑一跑,來看看如何使用的。

首先我們要編譯出我們的例子,這時候需要加上打開兩個編譯配置

CONFIG_SAMPLES

CONFIGSAMPLETRACE_EVENTS

編譯

make M=samples/trace_events

然后加載這個例子模塊

modprobe trace-events-sample

因為用戶接口在debugfs上,所以還要確保debugfs掛載了。

mount -t debugfs none /sys/kernel/debug/

此時我們就能在 /sys/kernel/debug/tracing/events/sample-trace/ 目錄下看到該模塊創(chuàng)建好的trace event了。

接下來,我們就可以打開這個探測時間,并且查看探測的輸出了。

cd /sys/kernel/debug/tracing

echo 1 > events/sample-trace/enable

cat trace

echo 0 > events/sample-trace/enable

通過cat trace觀察,可以看出系統(tǒng)運行時的一些狀態(tài)。

讓我們進一步再來看看events/sample-trace這個目錄:

可以看到

目錄名稱sample-trace由TRACE_SYSTEM這個宏定義,所以通過查找這個宏,就能知道有多少events的大類

每一個TRACE_EVENT都有一個自己的目錄

源文件中trace_XXX的函數(shù)就是執(zhí)行探測記錄的地方了。那么這些函數(shù)是怎么定義的呢?

TRACE_EVENT定義

看完了例子,我們就該看代碼實現(xiàn)了。講真,這是我見過的最長的宏展開了。之前在qemu上看到的那個hmp-command和這個比起來簡直就是個小屁孩。

先來看一下例子中是如何定義一個trace event的。和其他定義不同,定義trace event的定義在頭文件,而非源文件。我把trace-events-sample.h文件做一個簡要的打開。

中間我省略了很多TRACEEVENT及其變體,每一個TRACEEVENT對應(yīng)了一個trace point。

可以看到,一個trace event的定義需要涉及到起碼兩個頭文件。

史上最長宏定義

你以為就這么簡單嗎?當(dāng)然不是,作為有多年閱讀c語言代碼的老司機,看到真正的定義,我都差點沒有吐出來。。。

好了,不扯淡了。怎么能很好的解釋這個宏展開的過程呢?還是用一張圖吧。倒吸一口氣,準(zhǔn)備一次無盡的代碼閱讀。

終于完了,也不知道有沒有漏掉什么。。。大家如果真的想要看實際代碼中展開后的代碼,可以運行

make samples/trace_events/trace-events-sample.i

生成的文件是經(jīng)過預(yù)處理后得到的源代碼。不過相信我,你可能不太會愿意去看這個(捂臉)

回過頭來再看這展開,讓我們來總結(jié)一下這個過程:

一共包含了兩個頭文件:linux/tracepoint.h 和 trace/define_trace.h

在trace/definetrace.h中,反復(fù)定義了TRACEEVENT且再次包含samples/trace_events/trace-events-sample.h,實現(xiàn)了一個宏定義多次展開的效果

究竟定義了什么?

哪怕有了上面這個圖,我想大部分人也是不會去看的?;蛘哒f,看了可能也不知道這些宏展開究竟定義了些什么?

幫人幫到底,送佛送到西

既然都幫大家做了宏展開,那我就干脆再用一張圖展示一下這么多宏定義究竟定義了些什么。

經(jīng)過了一番云里霧里的宏展開,實際上就是(主要)定義出了這么一個數(shù)據(jù)結(jié)構(gòu) --traceeventcall。而且這個數(shù)據(jù)結(jié)構(gòu)關(guān)聯(lián)了幾個重要的小伙伴

tracepoint

trace_event_class

trace_event

后續(xù),我們將逐漸看到在初始化和使能的過程中,這些數(shù)據(jù)結(jié)構(gòu)之間的愛恨情仇。

注冊trace_event

有了數(shù)據(jù)結(jié)構(gòu),想要使用這個功能,我們能想到的第一步就是要把相關(guān)的數(shù)據(jù)結(jié)構(gòu)注冊到某個地方,這樣下次才能夠被使用到是不是?

這個秘密隱藏在了剛才宏展開的最后一次展開中,大家可以回過去搜“section("ftraceevents") &event##name;”。有內(nèi)核代碼經(jīng)驗的朋友可能已經(jīng)猜到了,這個意思是我們把一部分的內(nèi)容強制保存在了一個名為ftraceevents的section中。這些是什么呢?對了就是traceevent_call結(jié)構(gòu)體的指針們。

有了這個信息,我們再來看鏈接文件的定義:

我們看到ftraceevents這個section被包含在_startftrace_events之間。那就沿著這條線繼續(xù)。

看到了么?我們依次從_start|stopftraceevents之間拿出每一個內(nèi)容,再執(zhí)行eventinit()。而這個類型正好是traceeventcall,和剛才的定義吻合上。

但是eventinit()里面又調(diào)用了什么call->class->rawinit(call),這是什么個鬼?別急,這個我已經(jīng)給你寫好了。請?zhí)氐絼偛沤忉宼raceeventcall的圖上找找,這個rawinit函數(shù)就是traceeventrawinit。最后這個通過registertraceevent將traceeventcall.event注冊到系統(tǒng)中,而這個event的類型是trace_event。

怎么樣,是不是夠刺激的?

最后我們再來展示一下trace_event注冊到系統(tǒng)中后的樣子吧。

trace_event結(jié)構(gòu)會在兩個地方注冊:

ftraceeventlist:這個鏈表用來遍歷事件的號碼

event_hash[128]: 這個哈希表用來查找

有沒有看到其中funcs的成員第一個是之前定義的 tracerawoutput_##name?我猜這個就是最后輸出到trace文件的代碼,你覺得呢?

好了,數(shù)據(jù)結(jié)構(gòu)注冊完了,接下來是什么呢?

注冊traceeventcall

在上一節(jié)中,我們看到了內(nèi)核通過編譯鏈接的方法找到了traceeventcall,并且將其中的traceevent注冊到了系統(tǒng)中,現(xiàn)在我們來看看traceevent_call是如何注冊到系統(tǒng)中的。

這個過程就在event_init()函數(shù)下面一點。一共有兩個步驟:

添加到ftrace_events鏈表

添加到trace_array的events

第一步就在剛才的代碼片段中l(wèi)istadd(&call->list, &ftraceevents),而第二步則是通過函數(shù)_traceearlyaddevents()。

__trace_early_add_events() list_for_each(call, &ftrace_events, list) __trace_early_add_new_event(call, tr)

經(jīng)過這次注冊,將traceeventcall和trace_array連接了起來:

創(chuàng)建tracefs

在使用trace工具的時候,會通過tracefs往某些文件里讀寫來控制ftrace。trace_event也不例外,所以我們要先來看一下tracefs的構(gòu)建,為后續(xù)的代碼閱讀做好準(zhǔn)備。

說起來這個過程有點繞,因為創(chuàng)建tracefs的地方和剛才那些注冊函數(shù)不在一個地方(系統(tǒng)啟動時)。

具體細節(jié)可以看源代碼,這里解釋兩點:

createeventtoplevel_files 創(chuàng)建了和trace event相關(guān)的根目錄的一些文件

eventcreatedir則是會對每一個tracearray->events上的traceevent_file調(diào)用,創(chuàng)建每個event的目錄

而這個tracearray->events則是由, 剛才看到的函數(shù)traceearlyaddnew_event()添加的。

初始化過程的梳理

到這里估計你已經(jīng)暈了,沒事我自己寫得也暈了。讓我們來梳理一下整個初始化過程,明確一下這個注冊和tracefs的創(chuàng)建順序。

(1) 從特定的section中拿到traceeventcall數(shù)據(jù)結(jié)構(gòu),并注冊了trace_event

(2) 將traceeventcall添加到了ftrace_events鏈表

(3) 將每一個traceeventcall以traceeventfile的形式添加到trace_array.events

(4) 為每一個trace_array.events創(chuàng)建自己的tracefs

廢了這么大力氣我們都做了什么呢?

關(guān)聯(lián)了tracefs和traceeventfile,也就是我嗯定義的traceeventcall。

所以,每當(dāng)我們操作一個tracefs文件的時候,后面就對應(yīng)這相應(yīng)的traceeventfile和traceeventcall了。

OK, 我們已經(jīng)為tracefs的操作做好了準(zhǔn)備,讓我們來看看打開trace event選項時的動作吧。

打開事件

在查看trace文件中的事件記錄前,我們需要使能這個事件。

echo 1 > events/sample-trace/enable

所以有個開關(guān)來控制事件。而當(dāng)我們寫這個文件的時候,觸發(fā)到的內(nèi)核函數(shù)就是剛才我們注冊tracefs對應(yīng)的ops中的eventenablewrite。

繞暈了,其實呢就是通過某種方式設(shè)置了tracepoint結(jié)構(gòu)體中的funcs成員。剛才我們在traceeventcall結(jié)構(gòu)體中已經(jīng)看到了tracepoint結(jié)構(gòu),這次該好好看一眼了。

主角終于登場了,經(jīng)過這么一頓騷操作后,我們將之前定義好的 traceeventrawevent##name掛到了tracepoint的funcs列表中。當(dāng)然我還省去了重要的一步--設(shè)置key。

輸出事件

終于到了最后了。之前說的都是定義和初始化,終于要看到調(diào)用的情況了。在例子中我們看到,當(dāng)我們需要輸出一個事件時,就會調(diào)用trace_XXX()。這次該輪到它出場了。

先來看看trace_XXX這個函數(shù)的定義,它也藏在了我們剛才宏定義的展開中,這次我們仔細看一眼

每次我們調(diào)用traceXXX()函數(shù)的時候,先檢查key是否使能了,如果使能了才繼續(xù)往下走。接著我們再打開DOTRACE來看看。

聯(lián)系上上一小節(jié)的tracepoint結(jié)構(gòu)體是不是能想到啥?對了,就是遍歷tracepoint->funcs數(shù)組,然后調(diào)用它們。

好了,終于完整的看完了TRACE_EVENT的定義和使用流程。小編累了,大家也累了,今天就到這里吧。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11826

    瀏覽量

    219620
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7646

    瀏覽量

    146211
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    689

    瀏覽量

    31526

原文標(biāo)題:Linux TraceEvent - 我見過的史上最長宏定義

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    【快速溫變循環(huán)】快速溫變循環(huán)試驗箱的“循環(huán)”之道:展科技如何定義“一個循環(huán)”

    在軍工、航天、汽車電子等高端制造領(lǐng)域,快速溫變循環(huán)試驗是驗證產(chǎn)品可靠性的核心手段。然而,“一個循環(huán)”到底如何定義?是簡單的升降溫,還是對速率、駐留時間、溫變曲線精度、循環(huán)重復(fù)性的嚴苛約束?廣東
    的頭像 發(fā)表于 04-16 09:38 ?352次閱讀
    【快速溫變循環(huán)】快速溫變循環(huán)試驗箱的“循環(huán)”之道:<b class='flag-5'>宏</b>展科技如何<b class='flag-5'>定義</b>“一個循環(huán)”

    極速溫變 精準(zhǔn)可靠 —— 廣東展快速溫變箱的技術(shù)實力與行業(yè)應(yīng)用

    電子、汽車、醫(yī)療等行業(yè)的優(yōu)選測試方案。一、核心性能參數(shù):從溫域到速率,定義測試精度展快速溫變箱的性能參數(shù)直接對標(biāo)國際一線水平,為嚴苛測試提供堅實基礎(chǔ):·溫域覆蓋:
    的頭像 發(fā)表于 03-28 10:08 ?189次閱讀
    極速溫變 精準(zhǔn)可靠 —— 廣東<b class='flag-5'>宏</b>展快速溫變箱的技術(shù)實力與行業(yè)應(yīng)用

    低成本鍵盤旋鈕開源項目介紹

    辦公切軟件、調(diào)參數(shù)太繁瑣?創(chuàng)作時控筆刷 / 縮放總找快捷鍵?商用鍵盤價格高,還難適配個性化操作需求?想自制鍵盤,卻遇設(shè)計復(fù)雜、組裝難度高的問題?
    的頭像 發(fā)表于 03-25 11:09 ?583次閱讀

    debian image-69上自定義 linux 的啟動問題求解

    我構(gòu)建了自定義內(nèi)核,但我在加載它時遇到問題。 啟動掛起: [ 1.052175] 釋放未使用的內(nèi)核映像 (initmem) 內(nèi)存:2168K [ 1.068868] 將 /init 作為 init
    發(fā)表于 03-20 07:25

    微科技首家歐洲全資子公司正式成立

    在國家積極鼓勵企業(yè)“走出去”及共建“一帶一路”倡議的宏大背景下,國內(nèi)功率半導(dǎo)體領(lǐng)域的領(lǐng)先企業(yè)——江蘇微科技股份有限公司(以下簡稱“微科技”)今日宣布,其首家歐洲全資子公司 MacMic
    的頭像 發(fā)表于 03-04 11:06 ?677次閱讀

    C語言中實現(xiàn)函數(shù)的三種方式

    1. 函數(shù)介紹 函數(shù),即包含多條語句的定義,其通常為某一被頻繁調(diào)用的功能的語句封裝,且不想通過函數(shù)方式封裝來降低額外的彈棧壓棧開銷。 函數(shù)
    發(fā)表于 12-29 07:34

    泰科技與ADI正式簽署合作備忘錄

    近日,南京泰半導(dǎo)體科技股份有限公司(以下簡稱“泰科技”)與全球領(lǐng)先的高性能半導(dǎo)體公司ADI正式簽署合作備忘錄,雙方將在半導(dǎo)體測試與精密信號測量領(lǐng)域展開持續(xù)深度合作,共同推動高性能測試系統(tǒng)的技術(shù)創(chuàng)新與市場應(yīng)用落地。
    的頭像 發(fā)表于 12-02 09:09 ?1737次閱讀

    Linux內(nèi)核模塊的加載機制

    可能會有限制。 接下來是模塊的初始化。內(nèi)核會執(zhí)行模塊的初始化函數(shù),通常是用module_init定義的函數(shù)。這個函數(shù)負責(zé)模塊的啟動工作,比如注冊設(shè)備驅(qū)動或文件系統(tǒng)。如果初始化成功,模塊就被標(biāo)記
    發(fā)表于 11-25 06:59

    C語言拼接運算符典型使用

    在C語言中,##運算符(稱為[size=16.002px]標(biāo)記拼接運算符)用于定義中將兩個標(biāo)記(token)拼接成一個新的標(biāo)記。它在預(yù)處理階段處理,常用于動態(tài)生成變量名、函數(shù)名或類型名,以提高代碼
    發(fā)表于 11-20 08:27

    Linux史上10件最有意義的大事,你知道幾件?

    個傳奇。 今天,我們就帶你回顧? Linux 發(fā)展史上最有意義的十件大事 ,看看它如何一步步改變了世界。 一、1991:Linus Torvalds發(fā)布第一版Linux內(nèi)核 1991 年 8 月,芬蘭
    的頭像 發(fā)表于 10-20 11:10 ?544次閱讀

    RT_USING_TIMER_SOFT定義是否一定要開啟?

    定義 :RT_USING_TIMER_SOFT 請問:如果沒有使能軟件定時器的定義,只在創(chuàng)建定時器時,通過RT_TIMER_FLAG_SOFT_TIMER是否可以創(chuàng)建一個軟件定
    發(fā)表于 09-29 07:11

    SConscript結(jié)果與rtconfig.h中定義相反,是什么原因呢?

    當(dāng)我在rtconfig.h中把定義注釋時,添加了構(gòu)建 當(dāng)我取消定義注釋時,反而排除了構(gòu)建 SConscript結(jié)果與rtconfig.h中
    發(fā)表于 09-23 06:01

    IEC 62353中常用的術(shù)語和定義

    本文詳細解讀IEC 62353標(biāo)準(zhǔn)中的關(guān)鍵術(shù)語,包括被測設(shè)備(DUT/EUT)、應(yīng)用部分(B/BF/CF型)、泄漏電流、微電擊與電擊等定義,幫助理解醫(yī)療電氣設(shè)備安全測試要求。
    的頭像 發(fā)表于 07-29 17:27 ?903次閱讀

    Vicor助力發(fā)打造主動懸架電源系統(tǒng)

    廈門發(fā)電聲股份有限公司(發(fā))打造業(yè)內(nèi)性能卓越的主動懸架電源系統(tǒng),旨在將長期以來僅見于豪華車型的功能引入中端車型。發(fā)成功突破困擾知名汽車技術(shù)供應(yīng)商幾十年的技術(shù)瓶頸,在滿足主動懸架系統(tǒng)對尺寸、重量及瞬態(tài)性能的嚴苛需求的同時,兼
    的頭像 發(fā)表于 06-04 15:24 ?1375次閱讀

    5類網(wǎng)線最長傳輸距離是多少

    5類網(wǎng)線的最長傳輸距離在理論上為100米,但在實際應(yīng)用中,其有效傳輸距離通常不超過80米。以下是具體分析: 理論傳輸距離 國際標(biāo)準(zhǔn):5類網(wǎng)線的理論最大傳輸距離基于國際標(biāo)準(zhǔn)(如TIA/EIA-568
    的頭像 發(fā)表于 05-28 09:32 ?3089次閱讀
    平和县| 封丘县| 拜城县| 阿鲁科尔沁旗| 南投市| 澎湖县| 太湖县| 莒南县| 廊坊市| 京山县| 义马市| 广德县| 汉沽区| 溆浦县| 崇左市| 精河县| 保德县| 苍梧县| 金溪县| 固原市| 潞西市| 江永县| 巴东县| 千阳县| 咸宁市| 巫溪县| 宁武县| 五家渠市| 沂水县| 嘉峪关市| 五指山市| 桐柏县| 兴隆县| 宜宾县| 济源市| 玛多县| 巴马| 南雄市| 宜兰县| 霍州市| 彩票|