Linux應用程式獲取執行緒棧的資訊

shanyu20發表於2024-04-22

一. 參考網址

  1. Linux應用程式設計:用一種討巧方式,來獲取執行緒棧的使用資訊

  2. chatGPT的輸出

二. 程式碼實戰

  1. 適用於ARM的彙編程式碼

 1 #define _GNU_SOURCE    //沒有此句話,則編譯會出錯
 2 
 3 #include <stdio.h>
 4 #include <string.h>
 5 #include <pthread.h>
 6 #include <unistd.h>
 7 #include <sys/resource.h>
 8 
 9 typedef char s8;
10 typedef unsigned char u8;
11 typedef int s32;
12 
13 s32 PrintThreadStackInfo(s8 *comment)
14 {
15     size_t used, avail;
16     pthread_attr_t attr;
17     void *stack_addr;
18     size_t stack_size;
19     size_t esp_val;        // 獲取棧暫存器 ESP 的當前值
20     
21 #if 0
22     asm("movl %%esp, %0" : "=m"(esp_val) :);        //X86彙編
23 #else
24     asm volatile ("mov %0, sp\n" : "=r" (esp_val));    //Arm彙編
25 #endif
26     // 透過執行緒屬性,獲取棧區的起始地址和空間總大小
27     memset(&attr, 0, sizeof(pthread_attr_t));
28     pthread_getattr_np(pthread_self(), &attr);
29     pthread_attr_getstack(&attr, &stack_addr, &stack_size);
30     pthread_attr_destroy(&attr);
31     avail = esp_val - (size_t)stack_addr;
32     used = stack_size - avail;
33 
34     if (comment)
35         printf(comment);
36     printf("espVal = 0x%x \n", esp_val);
37     printf("statck top = %p \n", stack_addr);
38     printf("stack bottom = %p \n", stack_addr + stack_size);
39     printf("***stack info: used = %ld, avail = %ld, total = %lu***\n", 
40             used, avail, stack_size);
41     
42     return SUCCESS;
43 }

  2. 編譯註意事項

  1)函式:pthread_getattr_np

  3. chatGPT輸出

對不起,我的錯誤。你可以使用`pthread_getattr_np`函式和`pthread_attr_getstack`函式來獲取當前執行緒的棧資訊。這裡是一個修改後的示例程式碼:

```c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

// 獲取棧資訊的函式
void print_stack_info() {
    pthread_attr_t attr;
    size_t stack_size;
    void *stack_addr;

    // 初始化attr物件
    pthread_getattr_np(pthread_self(), &attr);

    // 獲取棧大小和棧地址
    pthread_attr_getstack(&attr, &stack_addr, &stack_size);

    // 計算已使用的棧空間大小
    unsigned long current_sp;
    asm volatile ("mov %0, sp\n" : "=r" (current_sp));
    long used_stack_size = (char*)stack_addr + stack_size - (char*)current_sp;

    // 計算剩餘的棧空間大小
    long free_stack_size = stack_size - used_stack_size;

    // 列印棧資訊
    printf("Stack Address: %p\n", stack_addr);
    printf("Stack Size: %lu bytes\n", stack_size);
    printf("Used Stack Size: %ld bytes\n", used_stack_size);
    printf("Free Stack Size: %ld bytes\n", free_stack_size);

    // 銷燬attr物件
    pthread_attr_destroy(&attr);
}

int main() {
    // 建立一個執行緒,並在其中呼叫print_stack_info函式
    pthread_t thread;
    pthread_create(&thread, NULL, (void *)print_stack_info, NULL);
    pthread_join(thread, NULL);

    return 0;
}
```

在這個修改後的示例程式碼中,我們使用`pthread_getattr_np`函式獲取當前執行緒的屬性,並使用`pthread_attr_getstack`函式獲取棧的大小和地址。然後,我們使用匯編語言的方式獲取當前棧指標位置,從而計算已使用的棧空間大小。最後,我們計算剩餘的棧空間大小並列印所有的棧資訊。

  

相關文章