C++ 如何从父线程提取pthread的taskid(tid)?
我正在使用std::thread来启动线程。另外,我需要在C++ 如何从父线程提取pthread的taskid(tid)?,c++,linux,pthreads,C++,Linux,Pthreads,我正在使用std::thread来启动线程。另外,我需要在/proc/[pid]/tasks/[tid]上提供工作线程的统计信息。我需要tid能够监视线程状态。我想知道是否有办法从父线程中提取tid。我知道来自worker的syscall gettid()返回它的id,但我希望从主线程而不是从线程返回threadId。有没有一种方法可以从std::thread.get_tid()的线程id gor中提取tid 我相信可能有更好的方法,请建议:) 更新: 这提供了一些关于从工作线程获取tid的信息
/proc/[pid]/tasks/[tid]
上提供工作线程的统计信息。我需要tid能够监视线程状态。我想知道是否有办法从父线程中提取tid
。我知道来自worker的syscall gettid()返回它的id,但我希望从主线程而不是从线程返回threadId。有没有一种方法可以从std::thread.get_tid()的线程id gor中提取tid
我相信可能有更好的方法,请建议:)
更新:这提供了一些关于从工作线程获取tid的信息,增加了线程启动的开销。例如,
std::thread t=std::thread(&wrapper)
t.get_id()
可以从启动程序线程调用。我正在/正在寻找是否有一个安全的方法从主/启动器线程执行相同的操作。所有线程都有一个唯一的id:std::thread::id this_id=std::this_thread::get_id()代码>
您可以在程序启动时将其存储在变量中,并且可以从其他线程访问它
我理解你所说的父线程的意思,但即使一个线程生了另一个线程,它们也是兄弟姐妹
如果希望主线程能够获取每个工作线程的/proc
路径,可以将工作线程对象包装在一个类中,该类在启动实际线程时创建一个主线程稍后可以获取的路径属性
例如:
#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 running\n";
}
}
};
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 running\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
int main() {
AutoStartThread a;
std::cout << a.get_proc_path() << "\t// AutoStartThread, will have path\n";
ManualStartThread b;
std::cout << b.get_proc_path()
<< "\t// ManualStartThread not started, no path\n";
b.start();
std::cout << b.get_proc_path()
<< "\t// ManualStartThread will now have a path\n";
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();
}
您可以通过一个函数启动线程,该函数的第一个任务是传递其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=%lu\n", (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=%lu\n", (long unsigned)msg.tid);
pthread_join(ptid,0);
}
#包括
#包括
#包括
#包括
结构tid_msg{
pthread_mutex_t mx;
pthread_cond_t cond;
pid_t tid;
};
无效*thr(无效*A)
{
结构tid_msg*msg=A;
pid\u t tid=syscall(SYS\u gettid);
pthread_mutex_lock(&msg->mx);
msg->tid=tid;
pthread_mutex_unlock(&msg->mx);
pthread_cond_信号(&msg->cond);
printf(“我的tid=%lu\n”,(长未签名)tid);
返回0;
}
int main()
{
struct tid_msg msg={PTHREAD_MUTEX_初始值设定项,PTHREAD_COND_初始值设定项,-1};
pthread\u ptid;
pthread_创建(&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(“他们的tid=%lu\n”,(长未签名)msg.tid);
pthread_join(ptid,0);
}
或者简单地通过一个原子变量(这里宽松的内存顺序应该很好,
但您可以出于安全考虑,使用顺序一致的默认值):
#包括
#包括
#包括
#包括
#包括
无效*thr(无效*A)
{
_原子pid_t*tidp=A;
pid_t tid;
tid=syscall(SYS\u gettid);
原子存储显式(tidp、tid、内存顺序);
printf(“我的tid=%lu\n”,(长未签名)tid);
返回0;
}
int main()
{
_原子pid_t tid=-1;
pthread\u ptid;
pthread_创建(&ptid、0、thr和tid);
而(-1==原子加载显式(&tid,内存顺序松弛));
printf(“他们的tid=%lu\n”,(长未签名)tid);
pthread_join(ptid,0);
}
线程与后续-前置等进程没有关系。可能的重复:可能的重复实际上与我想要的相反,我不喜欢使用worker中的getId()(我觉得它会使性能膨胀,因为需要使用gaurd或不断检查全局变量以填充tid)。例如,使用std::thread t=std::thread(&wrapper)代码>t.get_id()
从main的上下文将给出实际的线程id。您认为如何?好的,我明白了。当然,您可以用另一种方法来执行此操作,以便主服务器查询辅助服务器的路径。只需为每个线程添加一个condition\u变量
,该线程向master发出本机pid\u t
已放入map
的信号。也许最好在thread对象周围创建一个类,并进行一些同步,这样您就可以安全地执行th.get_path()
。@ShashankHegde制作了一个新版本。希望这次我说对了:)这两个选项基本上都在等待CV旋转。我想知道哪个选项对性能更好?特别是当有很多线程需要管理时?非常感谢:)@ShashankHegde我敢打赌旋转版本(原子)。线程创建的时间不应该长到足以保证父线程处于睡眠状态。
#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=%lu\n", (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=%lu\n", (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=%lu\n", (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=%lu\n", (long unsigned)tid);
pthread_join(ptid,0);
}