你瞭解linxu下的線程id嗎?

背景

最近在實現一個日誌庫時,需要記錄線程id,我採用C++ 11中的std::thread api獲取,如下例子代碼:

#include <thread>
#include <iostream>

int main()
{
    std::thread::id tid = std::this_thread::get_id();
    std::cout << tid << std::endl;
    std::getchar();
}

輸出

3676

上面是在windows上vs2015獲取的tid值,看着是一個整型,很正常。

如果在linux g++ 環境下編譯,輸出如下:

139627072304960

一長串奇怪的數字,看到這個結果,我很詫異,在我的印象中,它應該跟windows下輸出一樣,是個正常的數字(沒這麼長)。爲什麼會有這樣的印象:

我在linux調試程序時,通過top -Hp pid命令看到的進程中線程的id(在我的理解中)是這樣的:

top -Hp 18156

PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
18156 mjh       20   0   22996   1112    936 S  0.0  0.0   0:00.00 threadid
18157 mjh       20   0   22996   1112    936 S  0.0  0.0   0:00.00 threadid

如上top -Hp 命令,查看pid爲18156的進程中線程資源佔用情況,第一列PID理解成線程ID。這個值不像上面的程序那樣返回一長串數字。
所以我認爲g++ 下的std::thread::id的實現與我所理解的線程ID不一樣。所以我寫下面的一個測試代碼(通過pthread_self獲取thread id)

#include <iostream>
#include <thread>

int main()
{
   std::cout<<std::this_thread::get_id()<<std::endl;
   std::cout<<pthread_self()<<std::endl;
   std::getchar();

}

在通過std::thread獲取thread id的同時,也通過pthread_self()獲取thread id,結果如下:

140586156734272
140586156734272

值一樣,說明std::thread::get_id()獲取的就是thread id。那麼可以肯定,是我對thread id的理解有誤了,那top -Hp 看到線程pid是什麼?它跟thread id有什麼不一樣?

結論

通過一頓猛如虎的搜索,終於搞清楚了這些id的意義:

pthread_xxx系列API是POSIX中的標準,linux對pthread庫的實現是通過內核級的輕量級進程來實現的。這些進程就跟普通的進程一樣,有自己的pid可以被單獨調度

那麼就很顯然了,top -Hp中的pid其實是內核中對應用戶態的線程的進程的pid

線程id是有線程庫所分配的,它是獨立於進程空間的,就是不同的進程間,線程id可能會一樣。線程id只在進程空間內有效。

g++中std::thread的實現也是基於pthread,產生線程ID只在進程空間內有效,通過 syscall(__NR_gettid) 獲取線程的PID。

那麼我們在實現諸如log這樣的工具庫時,應該記錄線程的PID,通過這個PID可以直接配合一些進程資源監控工具(比如:top)來使用。

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