女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

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

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

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

如何實時獲取棧的使用情況?

Linux閱碼場 ? 來源:IOT物聯(lián)網(wǎng)小鎮(zhèn) ? 作者:道哥 ? 2021-06-11 14:42 ? 次閱讀

對于線程的??臻g,相信各位小伙伴都不陌生。它有下面的這幾項特性:

操作系統(tǒng)分配固定的空間;

使用一個棧寄存器來保存實時位置;

后進先出。

poYBAGDDBxmAM_DoAABkwzITDso774.jpg

今天,我們不聊操作系統(tǒng)層面對棧的管理,只從應(yīng)用程序的角度,來看一下如何實時獲取棧的使用情況。

在一般的單片機/嵌入式程序開發(fā)過程中,在創(chuàng)建一個線程(或者稱作任務(wù))的時候,是可以指定給該線程分配多少??臻g的。

然后在調(diào)試的時候呢,周期性的打印出棧區(qū)的使用情況:消耗了多少空間,還剩余多少空間。

這樣的話,跑完每一個測試用例之后,就能得到一個大致的統(tǒng)計數(shù)據(jù),從而最終決定:需要給這個線程分配多少??臻g。

例如:在 ucOS 系統(tǒng)中,提供了函數(shù) NT8U OSTaskStkChk(INT8U prio, OS_STK_DATA *p_stk_data),來獲取一個任務(wù)的棧使用信息。

但是在 Linux 系統(tǒng)中,并沒有這樣類似的函數(shù),來直接獲取棧使用信息。

因此,為了得到此線程的已使用和空閑棧空間,必須通過其他的方式來獲取。

下面,就提供 2 種解決方案:正規(guī)軍方式和雜牌軍方式!

正規(guī)軍方式

在 Linux 系統(tǒng)中,在創(chuàng)建一個線程的時候,是可以通過線程屬性來設(shè)置:為這個線程分配多少的棧(stack)空間的。

如果應(yīng)用程序不指定的話,操作系統(tǒng)就設(shè)置為一個默認的值。

線程創(chuàng)建完畢之后,操作系統(tǒng)在內(nèi)核空間,記錄了這個線程的一切信息,當然也就包括給它分配的??臻g信息。

為了讓應(yīng)用層能夠獲取到這個信息,操作系統(tǒng)也提供了相應(yīng)的系統(tǒng)函數(shù)。代碼如下:

pthread_attr_t attr; void *stack_addr; int stack_size; memset(&attr, 0, sizeof(pthread_attr_t)); pthread_getattr_np(pthread_self(), &attr); pthread_attr_getstack(&attr, &stack_addr, &stack_size); pthread_attr_destroy(&attr); printf("statck top = %p ", stack_addr); printf("stack bottom = %p ", stack_addr + stack_size);

從上面這段代碼中可以看到,它只能獲取棧空間的地址開始以及總的空間大小,仍然不知道當前??臻g的實際使用情況!

我找了一下相關(guān)的系統(tǒng)調(diào)用,Linux 似乎沒有提供相關(guān)的函數(shù)。

怎么辦?只能迂回操作。

我們知道,在 Linux x86 平臺上,寄存器 ESP 就是來存儲棧指針的。對于一個滿遞減類型的棧,這個寄存器里的值,就代表了當前棧中最后背使用的、那個??臻g的地址。

因此,只要我們能夠獲取到 ESP 寄存器里的值,就相當于知道了當前這個棧有多少空間被使用了。

那么怎樣來獲取 ESP 寄存器的值呢?既然是寄存器,那就肯定是使用匯編代碼了。

很簡單,就 1 行:

size_t esp_val; asm("movl %%esp, %0" : "=m"(esp_val) :);

對不起,我錯了!應(yīng)該是 2 行代碼,忘記變量定義了。

對于匯編代碼不熟悉的小伙伴,可以參考之前總結(jié)的一篇文章:內(nèi)聯(lián)匯編很可怕嗎?看完這篇文章,終結(jié)它!

找到第 4 個示例,直接抄過來就行。

好了,拿到了以上的所有信息,就可以計算出棧的已使用和空閑空間的大小了:

pYYBAGDDByWAHho6AACNOzmIkjw086.jpg

把以上代碼放在一起:

#include #include #include #include #include #include void print_stack1() { size_t used, avail; pthread_attr_t attr; void *stack_addr; int stack_size; // 獲取棧寄存器 ESP 的當前值 size_t esp_val; asm("movl %%esp, %0" : "=m"(esp_val) :); // 通過線程屬性,獲取棧區(qū)的起始地址和空間總大小 memset(&attr, 0, sizeof(pthread_attr_t)); pthread_getattr_np(pthread_self(), &attr); pthread_attr_getstack(&attr, &stack_addr, &stack_size); pthread_attr_destroy(&attr); printf("espVal = %p ", esp_val); printf("statck top = %p ", stack_addr); printf("stack bottom = %p ", stack_addr + stack_size); avail = esp_val - (size_t)stack_addr; used = stack_size - avail; printf("print_stack1: used = %d, avail = %d, total = %d ", used, avail, stack_size); } int main(int argc, char *agv[]) { print_stack1(); return 0; }
雜牌軍方式

上面的正規(guī)軍方法,主要是通過系統(tǒng)函數(shù)獲取了線程的屬性信息,從而獲取了棧區(qū)的開始地址和棧的總空間大小。

為了獲取這兩個值,調(diào)用了 3 個函數(shù),有點笨重!

不知各位小伙伴是否想起:Linux 操作系統(tǒng)會為一個應(yīng)用程序,都提供了一些關(guān)于 limit 的信息,這其中就包括堆棧的相關(guān)信息。

這樣的話,我們就能拿到一個線程的??臻g總大小了。

此時,還剩下最后一個變量不知道:棧區(qū)的開始地址!

我們來分析一下哈:當一個線程剛剛開始執(zhí)行的時候,棧區(qū)里可以認為是空的,也就是說此時 ESP 寄存器里的值就可以認為是指向棧區(qū)的開始地址!

是不是有豁然開朗的感覺?!

但是,這仍然需要調(diào)用匯編代碼來獲取。

再想一步,既然此時棧區(qū)里可以認為是空的,那么如果在線程的第一個函數(shù)中,定義一個局部變量,然后通過獲取這個局部變量的地址,不就相當于是獲取到了棧區(qū)的開始地址了嗎?

如下圖所示:

poYBAGDDBy2AO4IjAAB0JZhoSaY067.jpg

我們可以把這個局部變量的地址,記錄在一個全局變量中。然后在應(yīng)用程序的其他代碼處,就可以用它來代表棧的起始地址。

知道了 3 個必需的變量,就可以計算棧空間的使用情況了:

// 用來存儲棧區(qū)的起始地址 size_t top_stack; void print_stack2() { size_t used, avail; size_t esp_val; asm("movl %%esp, %0" : "=m"(esp_val) :); printf("esp_val = %p ", esp_val); used = top_stack - esp_val; struct rlimit limit; getrlimit(RLIMIT_STACK, &limit); avail = limit.rlim_cur - used; printf("print_stack2: used = %d, avail = %d, total = %d ", used, avail, used + avail); } int main(int argc, char *agv[]) { int x = 0; // 記錄棧區(qū)的起始地址(近似值) top_stack = (size_t)&x; print_stack2(); return 0; }
更討巧的方式

在上面的兩種方法中,獲取棧的當前指針位置的方式,都是通過匯編代碼,來獲取寄存器 ESP 中的值。

是否可以繼續(xù)利用剛才的技巧:通過定義一個局部變量的方式,來間接地獲取 ESP 寄存器的值?

poYBAGDDBzSAGqsWAACfTuCL0kY932.jpg

void print_stack3() { int x = 0; size_t used, avail; // 局部變量的地址,可以近似認為是 ESP 寄存器的值 size_t tmp = (size_t)&x; used = top_stack - tmp; struct rlimit limit; getrlimit(RLIMIT_STACK, &limit); avail = limit.rlim_cur - used; printf("print_stack3: used = %d, avail = %d, total = %d ", used, avail, used + avail); } int main(int argc, char *agv[]) { int x = 0; top_stack = (size_t)&x; print_stack3(); return 0; }
總結(jié)

以上的幾種方式,各有優(yōu)缺點。

我們把以上 3 個打印堆棧使用情況的函數(shù)放在一起,然后在 main 函數(shù)中,按順序調(diào)用 3 個測試函數(shù),每個函數(shù)中都定義一個整型數(shù)組(消耗 4K 的??臻g),然后看一下這幾種方式的打印輸出信息:

// 測試代碼(3個打印函數(shù)就不貼出來了) void print_stack1() { ... } void print_stack2() { ... } void print_stack3() { ... } void func3() { int num[1024]; print_stack1(); printf(" ********* "); print_stack2(); printf(" ********* "); print_stack3(); } void func2() { int num[1024]; func3(); } void func1() { int num[1024]; func2(); } int main(int argc, char *agv[]) { int x = 0; top_stack = (size_t)&x; func1(); return 0; }

打印輸出信息:

espVal = 0xffe8c980 statck top = 0xff693000 stack bottom = 0xffe90000 print_stack1: used = 13952, avail = 8362368, total = 8376320 ********* esp_val = 0xffe8c9a0 print_stack2: used = 12456, avail = 8376152, total = 8388608 ********* print_stack3: used = 12452, avail = 8376156, total = 8388608

責任編輯:lq6

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

    關(guān)注

    0

    文章

    507

    瀏覽量

    20083
  • 棧空間
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    5504

原文標題:Linux應(yīng)用程序設(shè)計:用一種討巧方式,來獲取線程棧的使用信息

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

收藏 人收藏

    評論

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

    S32G3有沒有辦法從.map文件確定SRAM使用情況

    我有 NXP S32G3 板。我有 .map 文件。有沒有辦法從 .map 文件確定 SRAM 使用情況。 非常感謝幫助。
    發(fā)表于 04-08 06:00

    HarmonyOS NEXT 原生應(yīng)用/元服務(wù)-DevEco Profiler性能問題定界實時監(jiān)控

    步驟來查看應(yīng)用的實時資源使用情況。 您可以通過如下三種方式打開DevEco Profiler: 在DevEco Studio頂部菜單欄中選擇“View -> Tool Windows
    發(fā)表于 02-21 14:35

    HarmonyOS NEXT 原生應(yīng)用/元服務(wù)-DevEco Profiler性能問題定界實時監(jiān)控

    步驟來查看應(yīng)用的實時資源使用情況。 您可以通過如下三種方式打開DevEco Profiler: 在DevEco Studio頂部菜單欄中選擇“View -> Tool Windows
    發(fā)表于 02-20 10:14

    激光在Micro LED顯示技術(shù)的應(yīng)用情況

    探索激光技術(shù)的多元應(yīng)用與前沿進展 今天研習激光在微加工領(lǐng)域的應(yīng)用,核心內(nèi)容為激光在Micro LED顯示技術(shù)的應(yīng)用情況。《Recent progress of laser processing
    的頭像 發(fā)表于 12-07 11:16 ?1322次閱讀
    激光在Micro LED顯示技術(shù)的應(yīng)<b class='flag-5'>用情況</b>

    Linux下如何管理虛擬內(nèi)存 使用虛擬內(nèi)存時的常見問題

    查看虛擬內(nèi)存使用情況 : 使用 free 命令可以查看當前的虛擬內(nèi)存使用情況,包括物理內(nèi)存、交換空間等的使用情況。 調(diào)整交換空間大小 : 如果需要調(diào)整交換空間的大小,可以使用 swapoff 命令關(guān)閉現(xiàn)有的交換空間,然后使用
    的頭像 發(fā)表于 12-04 09:19 ?1241次閱讀

    如何獲取入口函數(shù)不是__iar_program_start的Program entry的stack使用情況

    問題 IAR中默認的入口函數(shù)是__iar_program_start,使能stack usage analysis之后: 生成的map文件中STACK USAGE章節(jié)里面會包含Program entry的stack使用相關(guān)信息: 如果對應(yīng)啟動代碼沒有使用默認的入口函數(shù)__iar_program_start,需要使用--entry鏈接器選項指定對應(yīng)的入口函數(shù)(以使用入口函數(shù)Reset_Handler為例): 但是使能stack usage analysis之后,生成的map文件中STACK USAGE章節(jié)里面沒有包含Program entry的stack使用相關(guān)信息: ? 原因 正常來說,編譯器可以生成每個函數(shù)的調(diào)用和stack使用
    的頭像 發(fā)表于 11-25 16:23 ?917次閱讀
    如何<b class='flag-5'>獲取</b>入口函數(shù)不是__iar_program_start的Program entry的stack<b class='flag-5'>使用情況</b>

    LMX2592正常使用情況下溫度大概有多少?

    你好,LMX2592如果將 OUTA_PD = 1;OUTB_PD = 1;為什么芯片還是很燙,正常使用情況下溫度大概有多少,對于溫度的變化可以提供一下參考嗎
    發(fā)表于 11-08 08:32

    TMS320C64x在高性能DSP應(yīng)用中的高速緩存使用情況

    電子發(fā)燒友網(wǎng)站提供《TMS320C64x在高性能DSP應(yīng)用中的高速緩存使用情況.pdf》資料免費下載
    發(fā)表于 10-21 09:43 ?0次下載
    TMS320C64x在高性能DSP應(yīng)用中的高速緩存<b class='flag-5'>使用情況</b>

    藍牙人員定位有哪些亮點功能?

    。進出廠統(tǒng)計根據(jù)人員定位情況詳細記錄外來人員進出廠時間和停留時長,實時統(tǒng)計各外來單位人員進出廠情況及數(shù)量。 標簽使用情況統(tǒng)計系統(tǒng)后臺會對標簽使用情況
    的頭像 發(fā)表于 09-13 11:05 ?426次閱讀
    藍牙人員定位有哪些亮點功能?

    利用IEC104協(xié)議遠程IO模塊實時監(jiān)測能源使用情況

    隨著城市化進程的加速,軌道交通作為高效、便捷的公共交通工具,其安全性和穩(wěn)定性日益受到重視。為了保障軌道交通設(shè)施的安全運行,軌道交通遠程能源監(jiān)測自動化系統(tǒng)應(yīng)運而生,其中,IEC104協(xié)議模塊BE190以其穩(wěn)定的性能和靈活性,成為該系統(tǒng)中的關(guān)鍵組件。 一、IEC104協(xié)議遠程IO模塊BE190概述 BE190是一款專為工業(yè)自動化設(shè)計的IEC104遠程I/O模塊,由鋇錸技術(shù)精心打造。該模塊不僅支持IEC104協(xié)議,還兼容Modbus TCP通信協(xié)議,為軌道交通遠程能源監(jiān)測自動化
    的頭像 發(fā)表于 08-27 14:41 ?647次閱讀

    如何使用SystemView的堆監(jiān)控功能

    SystemView能夠監(jiān)視應(yīng)用程序如何使用動態(tài)存儲。這意味著,如果應(yīng)用程序中使用了C或C++堆、自定義堆或RTOS提供的內(nèi)存池對象,我們可以跟蹤這些對象的使用情況。SystemView可以在一個
    的頭像 發(fā)表于 08-09 18:07 ?1215次閱讀
    如何使用SystemView的堆監(jiān)控功能

    嵌入式設(shè)備在遠端運行,會有偶發(fā)性代碼跑飛的情況,無法到現(xiàn)場調(diào)試的情況下如何檢查出問題?

    運行日志: 1、線程的優(yōu)先級; 2、線程當前的狀態(tài); 3、線程當前的位置; 4、線程的大小; 5、線程歷史中使用的最大位置; 6、線程剩余的運行節(jié)拍數(shù); 設(shè)備內(nèi)存使用日志: 1、堆棧使用
    發(fā)表于 07-22 15:05

    水電能耗監(jiān)測物聯(lián)網(wǎng)平臺的功能和價值

    傳感器和網(wǎng)關(guān)設(shè)備,平臺可以實時獲取并顯示電能和水的使用情況,使用戶能夠隨時掌握能耗動態(tài)。 2. 數(shù)據(jù)分析:平臺具備強大的數(shù)據(jù)分析能力,可以對歷史和實時數(shù)據(jù)進行多維度分析,生成各類報表和
    的頭像 發(fā)表于 07-15 15:55 ?694次閱讀

    Banana Pi BPI-M7 RK3588開發(fā)板在 Linux 上檢查 Rockchip NPU 使用情況

    如下介紹如何監(jiān)控 Rockchip 設(shè)備的 NPU 使用情況。 如今,新型設(shè)備開始配備內(nèi)置 AI 芯片。“AI 芯片”的正確技術(shù)術(shù)語是 NPU,即神經(jīng)處理單元。 如果您有板載 NPU
    的頭像 發(fā)表于 07-11 16:47 ?755次閱讀
    Banana Pi BPI-M7 RK3588開發(fā)板在 Linux 上檢查 Rockchip NPU <b class='flag-5'>使用情況</b>

    鴻蒙開發(fā)系統(tǒng)基礎(chǔ)能力:ohos.hidebug Debug調(diào)試

    使用hidebug,可以獲取應(yīng)用內(nèi)存的使用情況,包括應(yīng)用進程的靜態(tài)堆內(nèi)存(native heap)信息、應(yīng)用進程內(nèi)存占用PSS(Proportional Set Size)信息等;可以完成虛擬機內(nèi)存切片導出,虛擬機CPU Profiling采集等操作。
    的頭像 發(fā)表于 06-24 17:35 ?989次閱讀
    鴻蒙開發(fā)系統(tǒng)基礎(chǔ)能力:ohos.hidebug Debug調(diào)試