pthread_t 인쇄 방법
검색해 봤지만 만족스러운 답을 찾지 못했습니다.
pthread_t를 인쇄할 수 있는 휴대용 방법이 없다는 것을 알고 있습니다.
앱에서는 어떻게 하나요?
업데이트:
실제로는 pthread_t는 필요 없지만 디버깅메시지로 다른 스레드를 식별하는 작은 숫자 ID가 필요합니다.
시스템(64비트 RHEL 5.3)에서는 부호 없는 long int로 정의되어 있기 때문에 큰 숫자이기 때문에 인쇄하는 것만으로 디버깅 행에서 중요한 위치를 차지합니다.gdb는 어떻게 쇼트TID를 할당합니까?
표현인 16진수 됩니다.pthread_t
"CHANGE: "CHANGE: "CHANGE: " 。
void fprintPt(FILE *f, pthread_t pt) {
unsigned char *ptc = (unsigned char*)(void*)(&pt);
fprintf(f, "0x");
for (size_t i=0; i<sizeof(pt); i++) {
fprintf(f, "%02x", (unsigned)(ptc[i]));
}
}
ID에 pthread_t
다음과 같은 것을 사용할 수 있습니다(이번에는 iostream을 사용합니다).
void printPt(std::ostream &strm, pthread_t pt) {
static int nextindex = 0;
static std::map<pthread_t, int> ids;
if (ids.find(pt) == ids.end()) {
ids[pt] = nextindex++;
}
strm << ids[pt];
}
.pthread_t
서도 '아까운'을 수 .operator<
★★★★★★에pthread_t
, 냐냐std::map
님은 다음 요소에 대한 주문이 필요합니다.
bool operator<(const pthread_t &left, const pthread_t &right) {
...
}
이 경우 POSIX 표준은 더 이상 산술 타입일 필요가 없기 때문에 운영체제에 따라 달라집니다.
IEEE 이되어 IEEE 1003.1-2001/Cor 2-2004, XBD/TC2/D6/26 이 추가됩니다.
pthread_t
의 리스트로 , 「산술 타입」이 허가됩니다.pthread_t
구조물로 정의됩니다.
도 '내일'에 합니다.sys/types.h
해 주세요.pthread_t
실장되어 있습니다.그러면, 필요에 따라서 인쇄할 수 있습니다.이를 위한 휴대용 방법이 없고 사용 중인 운영체제를 말하지 않기 때문에 더 이상 할 말이 없습니다.
편집: 새로운 질문에 응답하기 위해 GDB는 새로운 스레드가 시작될 때마다 자체 스레드 ID를 할당합니다.
디버깅을 위해 gdb는 자체 스레드 번호(항상 단일 정수)를 프로그램 내의 각 스레드에 관련짓습니다.
각 스레드 내부에서 원하는 번호를 인쇄하는 경우, 시작할 때 사용하는 번호를 각 스레드에 지시하는 것이 가장 깔끔한 방법입니다.
GDB는 Linux의 단축 번호에 스레드 ID(kernel pid, LWP라고도 함)를 사용합니다.시험:
#include <syscall.h>
...
printf("tid = %d\n", syscall(SYS_gettid));
좋아, 이게 내 마지막 대답인 것 같아.실제 문제는 2가지입니다.
- 로깅을 위해 스레드의 짧은 고유 ID를 가져오는 방법.
- 어쨌든 스레드의 실제 pthread_t ID를 인쇄해야 합니다(적어도 POSIX 값에 링크하기 위해서).
1. POSIX ID 인쇄(pthread_t)
pthread_t는 단순히 바이트별로 16진수가 인쇄된 바이트 배열로 취급할 수 있습니다.그래서 어떤 고정 사이즈에 제한을 받지 않습니다.유일한 문제는 바이트 순서입니다.인쇄 바이트의 순서가 단순한 「int」인쇄의 순서와 같으면, 아마 마음에 들 것입니다.다음은 little-endian의 예이며, big-endian의 경우 순서만 되돌려야 합니다(정의 하에).
#include <pthread.h>
#include <stdio.h>
void print_thread_id(pthread_t id)
{
size_t i;
for (i = sizeof(i); i; --i)
printf("%02x", *(((unsigned char*) &id) + i - 1));
}
int main()
{
pthread_t id = pthread_self();
printf("%08x\n", id);
print_thread_id(id);
return 0;
}
2. 인쇄 가능한 더 짧은 스레드 ID를 가져옵니다.
제안된 경우 모두 실제 스레드 ID(posix)를 일부 테이블의 인덱스로 변환해야 합니다.그러나 크게 다른 두 가지 접근법이 있습니다.
2.1. 스레드를 추적합니다.
테이블 내의 모든 기존 스레드의 스레드 ID를 추적하여(이러한 pthread_create() 콜은 래핑해야 함), 실제 스레드 ID가 아닌 테이블인덱스만 취득하는 "오버로드된" id 함수를 가질 수 있습니다.이 방식은 내부 스레드 관련 디버깅 및 리소스 추적에도 매우 유용합니다.분명한 장점은 스레드 레벨의 트레이스/디버깅 기능의 부작용으로 향후 확장이 가능하다는 것입니다.단점은 스레드 생성/파괴를 추적해야 한다는 것입니다.
다음으로 부분 의사 코드의 예를 나타냅니다.
pthread_create_wrapper(...)
{
id = pthread_create(...)
add_thread(id);
}
pthread_destruction_wrapper()
{
/* Main problem is it should be called.
pthread_cleanup_*() calls are possible solution. */
remove_thread(pthread_self());
}
unsigned thread_id(pthread_t known_pthread_id)
{
return seatch_thread_index(known_pthread_id);
}
/* user code */
printf("04x", thread_id(pthread_self()));
2.2. 새 스레드 ID를 등록합니다.
로깅 중에 pthread_self()를 호출하여 스레드가 인식되면 내부 테이블을 검색합니다.이러한 ID를 가진 스레드가 생성된 경우 인덱스가 사용됩니다(또는 이전 스레드에서 다시 사용됨). 같은 순간에 동일한 ID가 2개도 없으므로 실제로 문제가 되지 않습니다.스레드 ID를 아직 알 수 없는 경우 새 항목이 생성되어 새 인덱스가 생성/사용됩니다.
장점은 단순함입니다.단점은 스레드 생성/파괴를 추적할 수 없다는 것입니다.이를 추적하려면 몇 가지 외부 메커니즘이 필요합니다.
예능, 예능, 예능, 예능, 을 받을 수 .pthread_t
「 」 「 」 、 「 」 。
printf("awesome worker thread id %p\n", awesome_worker_thread_id);
출력:
awesome worker 스레드 ID 0x440485e0
알아요, 이 실이 아주 오래됐어요.위의 글을 모두 읽고 깔끔하게 대처하기 위한 아이디어를 하나 더 추가하겠습니다.어쨌든 매핑 비즈니스(pthread_to를 int에 매핑)에 참여한다면 가독성을 한 단계 더 높일 수 있습니다.pthread_create_wrapper도 문자열이 필요하도록 만듭니다.스레드 이름Windows 및 Windows CE에서 이 "SetThreadName()" 기능을 이해하는 방법을 배웠습니다.장점:ID는 단순한 숫자일 뿐만 아니라 어떤 스레드가 어떤 목적을 가지고 있는지도 알 수 있습니다.
Centos 5.4 x86_64에서 pthread_t는 부호 없는 길이의 typeef입니다.
그러니, 우린 이걸 할 수 있어...
#include <iostream>
#include <pthread.h>
int main() {
pthread_t x;
printf("%li\n", (unsigned long int) x);
std::cout << (unsigned long int) x << "\n";
}
다음과 같은 작업을 수행할 수 있습니다.
int thread_counter = 0;
pthread_mutex_t thread_counter_lock = PTHREAD_MUTEX_INITIALIZER;
int new_thread_id() {
int rv;
pthread_mutex_lock(&thread_counter_lock);
rv = ++thread_counter;
pthread_mutex_unlock(&thread_counter_lock);
return rv;
}
static void *threadproc(void *data) {
int thread_id = new_thread_id();
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
GCC(이 경우 Clang도 동작)를 사용할 수 있는 경우는, 다음과 같이 할 수도 있습니다.
int thread_counter = 0;
static void *threadproc(void *data) {
int thread_id = __sync_add_and_fetch(&thread_counter, 1);
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
플랫폼이 이를 지원하는 경우 다음과 같은 옵션을 사용할 수 있습니다.
int thread_counter = 0;
int __thread thread_id = 0;
static void *threadproc(void *data) {
thread_id = __sync_add_and_fetch(&thread_counter, 1);
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
이 기능은 함수 호출에서 thread_id를 전달할 필요가 없다는 장점이 있지만 Mac OS에서는 작동하지 않습니다.
pthread_t가 단순한 숫자일 경우, 이것이 가장 간단합니다.
int get_tid(pthread_t tid)
{
assert_fatal(sizeof(int) >= sizeof(pthread_t));
int * threadid = (int *) (void *) &tid;
return *threadid;
}
룩업 테이블(pthread_t : int)
많은 단명 스레드를 시작하는 프로그램에서 메모리 누수가 발생할 수 있습니다.
의 바이트 해시 생성pthread_t
(구조, 포인터, 긴 정수 등) 룩업 테이블을 필요로 하지 않는 사용 가능한 솔루션이 될 수 있습니다.다른 해시와 마찬가지로 충돌 위험이 있지만 요건에 맞게 해시의 길이를 조정할 수 있습니다.
부호 없는 쇼트 기호로 변환한 후 마지막 16진수만 출력할 수 있습니다.결과 값은 필요에 따라 충분히 고유할 수 있습니다.
첫 번째 투고에 대한 보충 설명: 사용자 정의 유니언 유형을 사용하여 pthread_t를 저장합니다.
union tid {
pthread_t pthread_id;
unsigned long converted_id;
};
인쇄하고 싶을 때pthread_t
, 를 만듭니다.tid
할당하다tid.pthread_id = ...
, 그 후 인쇄tid.converted_id
.
James가 위에서 언급했듯이 가장 좋은 방법은 유형이 정의된 헤더를 보는 것입니다.
pthread_t의 정의는 pthreadtypes.h에서 찾을 수 있습니다.이 정의는 다음 URL에서 찾을 수 있습니다.
/usr/bits/pthreadtypes.h
언급URL : https://stackoverflow.com/questions/1759794/how-to-print-pthread-t
'programing' 카테고리의 다른 글
Java에서는 XML을 파일이 아닌 문자열로 해석하려면 어떻게 해야 합니까? (0) | 2022.08.15 |
---|---|
nuxt 가져오기 후크 요청을 취소하는 중 (0) | 2022.08.15 |
단순한 팁탑 확장 또는 prodemirror 플러그인 (0) | 2022.08.15 |
Vue 2 Larabel 5.3 웅변가가 개체에서 데이터를 검색할 수 없음 (0) | 2022.08.15 |
사용되지 않는 JPMS 모듈을 Java EE API로 대체 (0) | 2022.08.15 |