背景
最近在實現一個日誌庫時,需要記錄線程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)來使用。