国产无码免费,人妻口爆,国产V在线,99中文精品7,国产成人无码AA精品一,制度丝袜诱惑av,久久99免费麻辣视频,蜜臀久久99精品久久久久久酒店
        訂閱
        糾錯(cuò)
        加入自媒體

        Linux應(yīng)用程序設(shè)計(jì):如何獲取線程棧的使用信息?

        把以上代碼放在一起:

        #include <unistd.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        #include <pthread.h>
        #include <sys/resource.h>
        void print_stack1()

           size_t used, avail;
           pthread_attr_t attr;
           void *stack_addr;
           int stack_size;
           // 獲取棧寄存器 ESP 的當(dāng)前值
           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ū)的開始地址和棧的總空間大小。

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

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

        這樣的話,我們就能拿到一個(gè)線程的棧空間總大小了。

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

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

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

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

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

        如下圖所示:

        我們可以把這個(gè)局部變量的地址,記錄在一個(gè)全局變量中。然后在應(yīng)用程序的其他代碼處,就可以用它來代表?xiàng)5钠鹗嫉刂贰?/p>

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

        // 用來存儲(chǔ)棧區(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;

        更討巧的方式

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

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

        void print_stack3()

           int x = 0;
           size_t used, avail;
           // 局部變量的地址,可以近似認(rèn)為是 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)缺點(diǎn)。

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

        // 測(cè)試代碼(3個(gè)打印函數(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

        <上一頁  1  2  
        聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問題,請(qǐng)聯(lián)系舉報(bào)。

        發(fā)表評(píng)論

        0條評(píng)論,0人參與

        請(qǐng)輸入評(píng)論內(nèi)容...

        請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

        您提交的評(píng)論過于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

        • 看不清,點(diǎn)擊換一張  刷新

        暫無評(píng)論

        暫無評(píng)論

          人工智能 獵頭職位 更多
          掃碼關(guān)注公眾號(hào)
          OFweek人工智能網(wǎng)
          獲取更多精彩內(nèi)容
          文章糾錯(cuò)
          x
          *文字標(biāo)題:
          *糾錯(cuò)內(nèi)容:
          聯(lián)系郵箱:
          *驗(yàn) 證 碼:

          粵公網(wǎng)安備 44030502002758號(hào)

          主站蜘蛛池模板: 成人三级精品| 福利在线视频导航| 辽宁省| 色哟哟精品| 亚洲自拍制服| 差差差很依人| 熟女一区二区三区| 99zyz| 女生洗鸡鸡喷尿的视频无马赛克?舒坦直叫的骚货视频?亚洲着九九九视频影院 | 91在线小视频| 91黑丝视频| 3p视频在线观看| 视色网| 9191久久| 国产成人精品二三区波多野| 好色综合| 熟女爱V| 99在线观看视频| 亚洲第一网站| 丝袜熟女露出| 欧美在线视频99| 国产乡下妇女做爰视频| 91精品导航| 少妇AV在线| 人人肏| 日韩无码中出| 久久中文字幕人妻| 石嘴山市| 国产亚洲视频在线观看| 五月香蕉网| 国产avav| 国产色AV| 美女黄色网| 国精产品一区一区三区有限公司杨| 亚洲成人Av| 伊人九九网香蕉精品| 亚洲成人网在线| 毛片自拍| 熟妇自搞| 牛牛AV| 金塔县|