《軟件調試的藝術》學習筆記——GDB使用技巧摘要——Pthread線程調試


Unix下最普遍的線程包是POSIX標準的PthreadsPthreads使用的搶佔式線程管理策略,程序中的一個線程可能在任何時候被另一個線程中斷。所以,使用Pthreads開發的應用程序有些錯誤不太容易重現。

GDB線程相關命令彙總

1        info threads給出關於當前所有線程的信息

2        thread n改爲線程n,或者說是進入線程n的棧中進行觀察

3        break line_num thread n表示當線程n到達源碼行line_num時停止執行

4        break line_num thread n if expression上一命令增加條件斷點而已

加入懷疑線程之間有死鎖,可以用gdb進行調試定位。流程大致是:

·        gdb啓動或者插入待調試程序

·        當程序掛起時候,通過按下Ctrl+C組合鍵中斷它;

·        這個時候用info threads查看所有線程都在幹嘛,然後找到自己的工作線程(注意排除main線程和pthreads的管理線程)

·        分別查看自己的工作線程在幹嘛,用bt(backtrace)查看對應的幀,記得用thread n切換進入對應線程的幀

·        關注像__pthread_wait_for_restart_signal()lock等函數,如果有源碼的話,會比較方便地定位到具體的問題代碼位置

下面是一個簡單的例子。如果在worker線程裏面,上鎖和解鎖沒有匹配,則會發生死鎖

// finds the primes between 2 and n; uses the Sieve ofEratosthenes,  
// deleting all multiples of 2, all multiples of 3, allmultiples of 5,  
// etc.; not efficient, e.g. each thread should do deletingfor a whole  
// block of values of base before going to nextbase for more  
   
// usage:  sieventhreads n  
// where nthreads is the number of worker threads  
   
#include     <stdio.h>  
#include     <math.h>  
#include     <pthread.h>  
   
#define MAX_N    100000000  
#define MAX_THREADS 100  
   
// shared variables  
int nthreads,  //number of threads (not counting main())  
    n,  // upper bound of range in which to findprimes  
   prime[MAX_N+1],  // in the end,prime[i] = 1 if i prime, else 0  
    nextbase;  // next sieve multiplier to be used  
   
int work[MAX_THREADS]; // to measure how much work each thread does,  
                       // in terms of number of sieve multipliers checked  
// lock index for the shared variable nextbase  
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;  
   
// ID structs for the threads  
pthread_t id[MAX_THREADS];  
   
// "crosses out" all multiples of k, from k*k on  
void crossout(int k)  
{  int i;  
   
   for (i = k; i*k<= n; i++)  {  
      prime[i*k] = 0;  
   }  
}  
   
// worker thread routine  
void *worker(int tn) // tn is the thread number (0,1,...)  
{  int lim,base;  
   
   // no need to checkmultipliers bigger than sqrt(n)  
   lim = sqrt(n);  
   
   do  {  
      // get next sievemultiplier, avoiding duplication across threads  
      pthread_mutex_lock(&nextbaselock);  
      base = nextbase +=2;  
      pthread_mutex_unlock(&nextbaselock);  
   
         if (base <=lim)  {  
        work[tn]++;  // log work done bythis thread  
         // don'tbother with crossing out if base is known to be  
         // composite  
         if(prime[base])  
           crossout(base);  
      }  
      else return;  
   } while (1);  
}  
   
main(int argc, char **argv)  
{  int nprimes,  // number of primes found  
       totwork,  // number of base values checked  
       i;  
   void *p;  
   
   n = atoi(argv[1]);  
   nthreads =atoi(argv[2]);  
   for (i = 2; i <=n; i++)  
      prime[i] = 1;  
   crossout(2);  
   nextbase = 1;  
   // get threads started  
   for (i = 0; i <nthreads; i++)  {  
     pthread_create(&id[i],NULL,(void *) worker,(void *) i);  
   }  
   
   // wait for all done  
   totwork = 0;  
   for (i = 0; i <nthreads; i++)  {  
     pthread_join(id[i],&p);  
      printf(" %d  
          values of basedone  
          /n  
         ",work[i]);  
      totwork +=work[i];  
   }  
   printf("  
          %d  
          total valuesof base done  
          /n  
         ",totwork);  
   
   // report results  
   nprimes = 0;  
   for (i = 2; i <=n; i++)  
      if (prime[i]) nprimes++;  
   printf("thenumber of primes found was %d  
          /n  
         ",nprimes);  
}  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章