如何从父线程中提取 pthread 的 taskid(tid)? [英] How to extract taskid(tid) of a pthread from the parent thread?

查看:57
本文介绍了如何从父线程中提取 pthread 的 taskid(tid)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 std::thread 来启动线程.另外,我需要 /proc/[pid]/tasks/[tid] 中可用的工作线程的统计信息.我需要 tid 才能监控线程统计​​信息.我想知道是否有办法从父线程中提取 tid .我知道来自工作者的 syscall gettid() 返回它的 id,但我想要来自主而不是从的 threadId.有没有办法从 std::thread.get_tid() 的 thread_id gor 中提取 tid ?

I'm using std::thread to launch threads. Also, I need stats for the worker thread available at /proc/[pid]/tasks/[tid]. I need tid to be able to monitor thread stats. I was wondering if there was a way to extract tid from the parent thread. I know that syscall gettid() from the worker returns its id, but I want the threadId from the master and not the slave. Is there a way to extract tid from the thread_id gor from std::thread.get_tid() ?

我相信可能有更好的方法来做到这一点,请提出建议:)

I believe there might be better ways of doing this, please suggest :)

更新:
如何获取某个线程的 Linux 线程 IDstd::thread() 这提供了一些关于从工作线程获取 tid 的信息,增加了线程启动的开销.例如,可以从启动器线程调用 std::thread t = std::thread(&wrapper); t.get_id().我正在/正在寻找是否可以以安全的方式从主线程/启动器线程执行相同的操作.

UPDATE:
How can you get the Linux thread Id of a std::thread() this provides some information on getting tid from the worker, adds an overhead to the thread launch. For instance, std::thread t = std::thread(&wrapper); t.get_id() can be called from the launcher thread. I was/am looking if there was a to do the same thing from the main/launcher thread in a safe way.

推荐答案

所有线程都有一个唯一的 ID:
std::thread::id this_id = std::this_thread::get_id();

All threads have a unique id:
std::thread::id this_id = std::this_thread::get_id();

您可以在程序启动时将其存储在一个变量中,并且其他线程可以访问它.

You can store it in a variable when the program starts and it'll be accessible from the other threads.

我理解你说线程的意思,但即使一个线程生了另一个线程,它们也是兄弟姐妹.

I understand what you mean when you say parent thread, but even though one thread gave birth to another, they are siblings.

如果您希望 master 线程能够获取每个 worker 线程的 /proc 路径,您可以包装工作线程类中的对象,当它启动实际线程时,会创建一个 master 稍后可以获取的路径属性.

if you want the master thread to be able to get the /proc path to each worker thread, you could wrap the worker thread object in a class that, when it starts the actual thread, creates a path property that the master can later get.

示例:

#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();
}

可能的输出:

/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

这篇关于如何从父线程中提取 pthread 的 taskid(tid)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆