如何从父线程中提取 pthread 的任务 id(tid)
How to extract taskid(tid) of a pthread from the parent thread?
我正在使用std::thread来启动线程。另外,我需要 /proc/[pid]/tasks/[tid]
上可用的工作线程的统计信息。我需要 tid 才能监控线程统计信息。我想知道是否有办法从父线程中提取tid
。我知道来自worker 的系统调用 gettid(( 返回其 id,但我想要来自主站而不是从属服务器的 threadId。有没有办法从 std::thread.get_tid(( 的thread_id gor 中提取tid
?
我相信可能有更好的方法可以做到这一点,请建议:)
更新:
如何获取 std::thread(( 的 Linux 线程 ID 这提供了一些关于从worker获取tid的信息,增加了线程启动的开销。例如,可以从启动器线程调用std::thread t = std::thread(&wrapper);
t.get_id()
。我正在/正在查看是否有一个以安全的方式从主/启动器线程做同样的事情。
所有线程都有一个唯一的 id:
std::thread::id this_id = std::this_thread::get_id();
您可以在程序启动时将其存储在变量中,并且可以从其他线程访问它。
我明白你说父线的意思,但即使一个线生了另一个线,他们也是兄弟姐妹。
如果希望主线程能够获取每个工作线程的/proc
路径,则可以将工作线程对象包装在一个类中,该类在启动实际线程时会创建一个 path 属性,主线程稍后可以获取该属性。
举个例子:
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
// A base class for thread object wrappers
class abstract_thread {
public:
abstract_thread() {}
abstract_thread(const abstract_thread&) = delete;
abstract_thread(abstract_thread&& rhs) :
m_th(std::move(rhs.m_th)), m_terminated(rhs.m_terminated), m_cv{}, m_mtx{} {}
abstract_thread& operator=(const abstract_thread&) = delete;
abstract_thread& operator=(abstract_thread&& rhs) {
terminate();
join();
m_th = std::move(rhs.m_th);
m_terminated = rhs.m_terminated;
return *this;
}
virtual ~abstract_thread() {
// make sure we don't destroy a running thread object
terminate();
join();
}
virtual void start() {
if(joinable())
throw std::runtime_error("thread already running");
else {
std::unique_lock<std::mutex> lock(m_mtx);
m_terminated = true;
// start thread and wait for it to signal that setup has been done
m_th = std::thread(&abstract_thread::proxy, this);
m_cv.wait(lock, [this] { return m_terminated == false; });
}
}
inline bool joinable() const { return m_th.joinable(); }
inline void join() {
if(joinable()) {
m_th.join();
}
}
inline void terminate() { m_terminated = true; }
inline bool terminated() const { return m_terminated; }
protected:
// override if thread specific setup needs to be done before start() returns
virtual void setup_in_thread() {}
// must be overridden in derived classes
virtual void execute() = 0;
private:
std::thread m_th{};
bool m_terminated{};
std::condition_variable m_cv{};
std::mutex m_mtx{};
void proxy() {
{
std::unique_lock<std::mutex> lock(m_mtx);
setup_in_thread(); // call setup function
m_terminated = false;
m_cv.notify_one();
}
execute(); // run thread code
}
};
// an abstract thread wrapper capable of returning its /proc path
class proc_path_thread : public abstract_thread {
public:
// function to call from master to get the path
const std::string& get_proc_path() const { return m_proc_path; }
protected:
void setup_in_thread() override {
m_proc_path =
std::move(std::string("/proc/")) + std::to_string(syscall(SYS_gettid));
}
private:
std::string m_proc_path{};
};
// two different thread wrapper classes. Just inherit proc_path_thread and implement
// "execute()". Loop until terminated() is true (or you're done with the work)
class AutoStartThread : public proc_path_thread {
public:
AutoStartThread() { start(); }
private:
void execute() override {
while(!terminated()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << std::this_thread::get_id() << " AutoStartThread runningn";
}
}
};
class ManualStartThread : public proc_path_thread {
void execute() override {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << std::this_thread::get_id() << " ManualStartThread runningn";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
int main() {
AutoStartThread a;
std::cout << a.get_proc_path() << "t// AutoStartThread, will have pathn";
ManualStartThread b;
std::cout << b.get_proc_path()
<< "t// ManualStartThread not started, no pathn";
b.start();
std::cout << b.get_proc_path()
<< "t// ManualStartThread will now have a pathn";
b.join();
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
// terminate() + join() is called automatically when abstract_thread descendants
// goes out of scope:
//
// a.terminate();
// a.join();
}
可能的输出:
/proc/38207 // AutoStartThread, will have path
// ManualStartThread not started, no path
/proc/38208 // ManualStartThread will now have a path
139642064209664 ManualStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
您可以通过一个函数启动线程,该函数的第一个任务是向其发送 id 的消息,例如,经典地使用互斥体和 condvar:
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>
struct tid_msg{
pthread_mutex_t mx;
pthread_cond_t cond;
pid_t tid;
};
void *thr(void*A)
{
struct tid_msg *msg = A;
pid_t tid = syscall(SYS_gettid);
pthread_mutex_lock(&msg->mx);
msg->tid = tid;
pthread_mutex_unlock(&msg->mx);
pthread_cond_signal(&msg->cond);
printf("my tid=%lun", (long unsigned)tid);
return 0;
}
int main()
{
struct tid_msg msg = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, -1 };
pthread_t ptid;
pthread_create(&ptid,0,thr,&msg);
pthread_mutex_lock(&msg.mx);
while(-1==msg.tid) pthread_cond_wait(&msg.cond,&msg.mx);
pthread_mutex_unlock(&msg.mx);
printf("their tid=%lun", (long unsigned)msg.tid);
pthread_join(ptid,0);
}
或者只是通过一个原子变量(放松的内存排序在这里应该没问题,但您可以安全地使用它并使用顺序一致的默认值(:
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdatomic.h>
void *thr(void*A)
{
_Atomic pid_t *tidp = A;
pid_t tid;
tid = syscall(SYS_gettid);
atomic_store_explicit(tidp, tid, memory_order_relaxed);
printf("my tid=%lun", (long unsigned)tid);
return 0;
}
int main()
{
_Atomic pid_t tid=-1;
pthread_t ptid;
pthread_create(&ptid,0,thr,&tid);
while(-1==atomic_load_explicit(&tid,memory_order_relaxed)) ;
printf("their tid=%lun", (long unsigned)tid);
pthread_join(ptid,0);
}
- 从函数角度看ID到文件路径的内部与外部映射
- 通过组合不同的类型来创建唯一的id
- 我不断收到 [错误] ID 返回 1 退出状态错误,但看不到问题所在
- 有没有任务栏API可以立即应用注册表更改
- FFMPEG配置文件级别id大小无效
- 方法内部但循环仍得到预期的不合格id错误C++
- 如何获取 GLFW 窗口 ID?
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 如何创建线程序列以按照启动顺序执行任务?
- 显示数组中的学生 ID 和最高分
- C++:"("令牌"之前有预期的非限定 id 指向类中成员函数的指针
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- C++一个线程如何正确通信其任务已完成?
- 在线程之间拆分任务总是值得的吗?
- 递归求和任务的错误答案
- Xcode 9.4.1 中的 Apple Mach-O 链接器 (id) 错误
- 错误:令牌 { '{' 之前应存在非限定 ID
- 如何从父线程中提取 pthread 的任务 id(tid)
- 您可以在 OpenMP 中将特定线程 ID 分组到唯一的任务组中吗?
- c++登录任务计划错误:没有完成帐户名和安全id之间的映射