中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于linuxthreads-2.0.1如何分析線程的棧

發布時間:2021-12-09 09:33:04 來源:億速云 閱讀:136 作者:柒染 欄目:大數據

本篇文章為大家展示了基于linuxthreads-2.0.1如何分析線程的棧,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

線程本質上是進程中的一個執行流,我們知道,進程有代碼段,線程其實就是進程代碼段中的其中一段代碼。線程的一種實現是作為進程來實現的。通過調用clone,新建一個進程,然后執行父進程代碼段里的一個代碼片段。文件、內存等信息都是共享的。因為內存是共享的,所以線程不能共享棧,否則訪問棧的地址的時候,會映射到相同的物理地址,那樣就會互相影響,所以每個線程會有自己獨立的棧。在調用clone函數的時候會設置棧的范圍。下面通過linuxthreads的代碼看看線程的棧。linuxthreads里有一個__pthread_initialize函數,該函數會在main函數執行前執行。在該函數中會設置主線程的棧范圍。

   
     
 
    
    

// CURRENT_STACK_FRAME 即sp寄存器。按STACK_SIZE大小對齊
__pthread_initial_thread_bos = (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));              

__pthread_initial_thread_bos 保存主線程的棧頂位置。

然后當我們第一次調用pthread_create創建線程的時候,會調用pthread_initialize_manager函數初始化manager線程。manager線程是管理其他的線程的線程。

   
     
 
    
    

// 在堆上分配一塊內存用于manager線程的棧,棧頂
 __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
// 高地址是棧底
 __pthread_manager_thread_tos = __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;              

然后調用clone函數設置manager線程的棧。

   
     
 
    
    __clone(__pthread_manager,__pthread_manager_thread_tos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]);

最后在函數pthread_handle_create中設置創建的線程的棧,pthread_handle_create函數是調用pthread_create函數的時候被調用的函數。

   
     
 
    
    

// THREAD_STACK_START_ADDRESS 即__pthread_initial_thread_bos,即主線程的棧頂
#ifndef THREAD_STACK_START_ADDRESS
#define THREAD_STACK_START_ADDRESS  __pthread_initial_thread_bos
#endif
#define THREAD_SEG(seg) ((pthread_t)(THREAD_STACK_START_ADDRESS - (seg) * STACK_SIZE) - 1)
#define SEG_THREAD(thr) (((size_t)THREAD_STACK_START_ADDRESS - (size_t)(thr+1)) / STACK_SIZE)
pthread_t new_thread = THREAD_SEG(sseg);
mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -1, 0);              

從上面代碼可知,新建的線程的棧在主線程的棧頂下面(即地址小于主線程的棧頂),創建線程的時候,首先計算新線程的棧地址,然后調用mmap劃出這塊地址。否則訪問的時候會segmentfault。最后調用clone創建進程(線程)并設置棧的棧頂和棧底位置。

   
     
 
    
     __clone(pthread_start_thread, new_thread,(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND| PTHREAD_SIG_RESTART),new_thread);

內存布局如下。

基于linuxthreads-2.0.1如何分析線程的棧

從上面的棧分布我們還可以知道一個信息,即當前執行的代碼屬于哪個線程。

   
     
 
    
    

static inline pthread_t thread_self (void)
{
#ifdef THREAD_SELF
 THREAD_SELF
#else
 char *sp = CURRENT_STACK_FRAME;
 // 大于初始化棧則是主線程
 if (sp >= __pthread_initial_thread_bos)
   return &__pthread_initial_thread;
 // 這是manager線程自己申請的空間
 else if (sp >= __pthread_manager_thread_bos
  && sp < __pthread_manager_thread_tos)
   return &__pthread_manager_thread;
 else
   // sp肯定落在某個線程的棧范圍內,STACK_SIZE-1使得低n位全1, 或sp再加1即往高地址,按STACK_SIZE對齊,減去一個pthread_t得到tcb
   return (pthread_t) (((unsigned long int) sp | (STACK_SIZE - 1)) + 1) - 1;
#endif
}              

這就是linuxthreads獲取當前線程的是方法。

上述內容就是基于linuxthreads-2.0.1如何分析線程的棧,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

甘洛县| 关岭| 上犹县| 朝阳县| 广东省| 磐安县| 信阳市| 江西省| 汕尾市| 宜章县| 太湖县| 博客| 祁东县| 漠河县| 孟津县| 广宗县| 年辖:市辖区| 夹江县| 崇礼县| 绥化市| 渝北区| 宽甸| 广西| 砀山县| 光山县| 康定县| 大关县| 剑阁县| 武胜县| 湘潭市| 孝昌县| 桐城市| 滨海县| 略阳县| 北碚区| 玉环县| 吴忠市| 合川市| 宁安市| 佛山市| 阿拉尔市|