【问题标题】:Making a clone'd thread pthread compatible使克隆的线程 pthread 兼容
【发布时间】:2021-02-12 08:48:36
【问题描述】:

我在 Linux x86-64 上使用 C 语言进行编程。我正在使用一个库,它通过原始clone 系统调用而不是使用pthread_create 创建多个线程。这些线程运行库内部的低级代码。

我想钩住其中一个线程来内省它的行为。挂钩代码很容易,但我发现我几乎无法调用 libc 中的任何内容,因为未配置线程状态。 pthread_create 通常会将一堆数据插入到fs: 索引的线程本地存储区域中。例如,其中一些数据对于 libc 的函数至关重要,例如函数指针加密密钥 (pointer_guard) 和语言环境指针。

所以我的问题是:我可以通过任何机制将clone'd 线程升级到完整的pthread 吗?如果没有,有什么方法可以从clone'd 线程(例如printf、toupper 等需要libc 的线程本地数据)调用C 函数?

【问题讨论】:

    标签: multithreading pthreads glibc


    【解决方案1】:

    例如,其中一些数据对于 libc 的函数至关重要,例如函数指针加密密钥 (pointer_guard) 和语言环境指针。

    正确。不要忘记errno,它也在里面。

    我可以通过任何机制将克隆的线程升级为完整的 pthread 吗?

    没有。

    有什么方法可以从克隆线程调用 C 函数

    没有。

    如果您有库的源代码,用pthread_create 替换直接调用clone 应该相对容易。

    如果您不这样做,但该库以存档形式提供,您可以使用obcopy --rename-symbol 将其clone 调用重定向到替换(例如my_clone),然后可以创建一个新线程通过pthread_create 并调用该线程中的目标函数。这是否会成功很大程度上取决于图书馆对clone的细节的关心程度。

    这也可能不值得麻烦。


    更好的选择可能是实现内省而不调用libc。由于您的printf 和toupper 可能只需要处理ASCII 和C 语言环境,因此实现这些函数的有限版本并使用直接系统调用来编写输出并不难。

    【讨论】:

    • 啊,我没有考虑在库中替换clone,这是一个很好的尝试方向。然而,至少在一种情况下,它似乎有可能调用clone 从信号处理程序(我还没有证明这一事实)。我不认为pthread_create 是异步信号安全的。也许我可以尝试避免这种情况,嗯......我还假设通过“直接系统调用”我还需要避免 glibc 的包装器,因为它们可能会触及 TLS 中的errno,对吧?烦人,但我想这就是我使用图书馆的这种脚枪得到的结果......
    • 不能使用 pthread_create() 替换 clone(),因为 pthread_create() 是使用以下标志调用 clone():CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID |CLONE_CHILD_CLEARTID。 GLIBC 准备环境以使其中一些标志按预期工作,并将附加参数传递给 clone() 用于 CLONE_SETTLS、CLONE_PARENT_SETTID 等标志...因此,如果对 clone() 的原始调用不使用这些标志,程序将导致不同的行为。
    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多