• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            大龍的博客

            常用鏈接

            統計

            最新評論

            在linux上獲得線程id的方法

            在linux2.4版本后,linux使用了NPTL作為自己的線程庫,為了兼容POSIX標準,所以在內核task中有兩個域tgid和tid,前者是進程id,后者是線程id。在linux上獲得線程id的方法,目前我所知的有三種,當然這里的三種是指在用戶態的程序中,否則除非自己寫的kernel module, 都是調用編號224的系統調用實現的(2.6版本)。 

            第一種: gettid(), man gettid 可以看到gettid的使用方式。 
            使用時要先定義:_syscall0(pid_t, gettid) 
            其中_syscall0是一個宏(由于參數的不同還有_syscall1,_syscall2...),定義如下: 
            #define _syscall0(type,name) \ 
            type name(void) \ 
            { \ 
            long __res; \ 
            __asm__ volatile ("int $0x80" \   //int 80, 軟中斷 
                    : "=a" (__res) \          //輸入輸出都用的eax 
                    : "0" (__NR_##name)); \   //#define __NR_gettid 224 
            __syscall_return(type,__res); \   //返回tid 
            } 
            編譯時,宏展開之后,相當于定義了一個pid_t gettid(void)函數,用內嵌匯編實現,在程序中就可以使用gettid()獲得線程id了。 

            第二種:syscall(), 名字叫syscall(),卻是glibc中的庫函數。 
            使用方式:syscall(__NR_gettid), 其中__NR_gettid就是224,同上。 
            syscall的實現要到glibc中去找,不同的硬件平臺有不同的實現版本,在i386上的實現在syscall.S中: 
            #include <sysdep.h> 
            .text 
            ENTRY (syscall) 
            PUSHARGS_6 /* Save register contents.  */ 
            _DOARGS_6(44) /* Load arguments.  */ 
            movl 20(%esp), %eax /* Load syscall number into %eax.  */ 
            ENTER_KERNEL /* Do the system call.  */ 
            POPARGS_6 /* Restore register contents.  */ 
            cmpl $-4095, %eax /* Check %eax for error.  */ 
            jae SYSCALL_ERROR_LABEL /* Jump to error handler if error.  */ 
            L(pseudo_end): 
            ret /* Return to caller.  */ 
            PSEUDO_END (syscall) 
            其中ENTRY也是一個宏,展開了相當的長,主要用于在鏈接的時候讓gcc能夠"看見"并調用這段用匯編寫成的syscall()函數。 

            第三種:pthread_self() 
            同樣是一個glibc提供的函數,在linux的manual中說返回的是當前線程的thread ID.但是實際你看到的是一個很長的,似乎沒有規律的值。什么原因得看看它的實現: 
            在glibc中,pthread_self()返回的是THREAD_SELF,這又是一個宏 
            定義如下 
            # define THREAD_SELF \ 
              ({ struct pthread *__self;      \ 
                  asm ("movl %%gs:%c1,%0" : "=r" (__self)      \ 
             : "i" (offsetof (struct pthread, header.self)));      \ 
                  __self;}) 
            這段代碼返回了當前線程的descriptor,pthread_self()得到的就是這個descriptor的地址, 也就是unsigned long int類型的pthread_t。知道了這一點就好辦了,找到thread descriptor的定義: 
            struct pthread 
            { 
            ... 
                     pid_t tid; 
            ... 
            } 

            接下來知道怎么做了嗎?算好長度n,構造一個假的pthread結構。 
            struct pthread_fake 
            { 
            void *nothing[n]; 
            pid_t tid; 
            }; 
            用(struct pthread_fake *) pthread_self()->tid得到線程id了 
            相比前兩種做法,這種無疑是最繁瑣的,但是同理,可以獲取很多glibc中維護了,但是沒有提供訪問方法的數據。

            posted on 2010-12-28 14:34 大龍 閱讀(1207) 評論(0)  編輯 收藏 引用

            超级97碰碰碰碰久久久久最新| 久久午夜羞羞影院免费观看| 久久er国产精品免费观看8| 久久久久综合网久久| 久久中文字幕无码专区| 一本一本久久a久久综合精品蜜桃 一本一道久久综合狠狠老 | 亚洲v国产v天堂a无码久久| 亚洲精品乱码久久久久久中文字幕| 激情伊人五月天久久综合| 国产精品欧美久久久久天天影视 | 精品乱码久久久久久久| 国产免费久久精品99re丫y| 亚洲综合精品香蕉久久网97| 久久精品国产免费观看| 99久久亚洲综合精品网站| 亚洲精品乱码久久久久66| 久久国产成人午夜AV影院| 青青草国产精品久久| 久久无码人妻一区二区三区 | 日本五月天婷久久网站| 久久99精品久久久久久水蜜桃| 九九精品99久久久香蕉| 久久久久亚洲AV成人网人人网站| 久久99久久成人免费播放| 久久成人影院精品777| 久久99久久99精品免视看动漫| 久久久亚洲裙底偷窥综合| 久久久久亚洲AV无码专区桃色 | 久久久久久a亚洲欧洲aⅴ| 久久久久无码精品国产| 久久亚洲日韩精品一区二区三区| 久久人人添人人爽添人人片牛牛| 日批日出水久久亚洲精品tv| 久久综合九色综合久99| 色婷婷久久综合中文久久一本| 久久久久亚洲爆乳少妇无 | 亚洲色欲久久久综合网| 久久99热这里只有精品国产| 亚洲国产精品18久久久久久| 色婷婷综合久久久久中文| 久久久国产乱子伦精品作者|