【问题标题】:Different standard streams per POSIX thread每个 POSIX 线程的不同标准流
【发布时间】:2010-05-19 18:08:44
【问题描述】:

是否有可能为不同的 POSIX 线程实现不同的标准输出重定向,如 printf(3)?标准输入呢?

我有很多基于标准输入/输出的代码,我只能将这些代码分成不同的 POSIX 线程,而不是进程。 Linux操作系统,C标准库。 我知道我可以重构代码以将 printf() 替换为 fprintf() 并进一步采用这种风格。 但在这种情况下,我需要提供某种旧代码所没有的上下文。

那么没有人有更好的主意(查看下面的代码)吗?

#include <pthread.h>
#include <stdio.h>

void* different_thread(void*)
{
    // Something to redirect standard output which doesn't affect main thread.
    // ...

    // printf() shall go to different stream.
    printf("subthread test\n");

    return NULL;
}

int main()
{
    pthread_t id;
    pthread_create(&id, NULL, different_thread, NULL);

    // In main thread things should be printed normally...
    printf("main thread test\n");

    pthread_join(id, NULL);
    return 0;
}

【问题讨论】:

    标签: c multithreading unix posix stdio


    【解决方案1】:

    如果您使用clone 创建线程,您可以做任何您想做的事情,但 POSIX.1 规定线程必须共享打开的文件描述符。

    您可以尝试几种技巧,但您确实应该将调用转换为FILE * 参数接受函数。

    【讨论】:

    • 在技术上能够解决原始任务真的很好,但是在我更深入地分析了情况之后,我更愿意重新编写代码,因为我计划将来重用它,我不想引入任何看起来像 fork() 的东西(是的,这超出了原来的问题)。
    【解决方案2】:

    在 *nix 系统上,文件描述符上的 stdio 层和文件描述符对于进程是全局的。因此,如果不更改某些东西,就无法做你想做的事。最好的办法是使用 fprintf() 重写代码。由于这涉及向 arglist 添加参数,我什至不确定您是否能够在不修改实际代码的情况下使用预处理器技巧来实现您的目标。

    也许您可以澄清您无法创建新流程的原因?这个问题或许可以从这个角度解决。

    【讨论】:

      【解决方案3】:

      如果你有线程本地存储,你可以这样做:

      #undef printf
      #define printf(fmt, ...) fprintf(my_threadlocal_stdout, fmt, __VA_ARGS__)
      

      同样适用于您打算使用的所有其他 stdio 函数。当然最好不要尝试重新定义相同的名称,而是对源文件执行搜索和替换以使用替代名称。

      顺便说一句,即使编译器没有线程本地存储扩展,您也可以使用一个函数调用,该函数调用返回正确的 FILE * 供调用线程使用。

      【讨论】:

      • 实际上线程本地存储最终用于原始案例,但我反对全局 printf 重载,因为这可能会产生不可预知的影响。我停留在基于线程本地存储的最少重新设计的界面和内部隐藏的上下文上。这既提供了兼容的界面,又提供了良好的工作解决方案。限制是每个客户端线程一个上下文,这对我来说是可以接受的。
      【解决方案4】:

      如果你坚持使用像“printf()”这样的标准 I/O 函数,那么我能想到的唯一方法是让标准 I/O 库支持线程特定的 I/O,使用线程局部数据结构(类似于“errno”是一个宏,它调用一个返回线程局部错误号的函数)。我不知道执行此操作的标准 I/O 的任何实现。

      【讨论】:

      • 是的,我需要一些方法来进行这种线程本地标准 I/O 重定向。原始代码是从 VxWorks 移植而来的,这个操作系统有类似这样的本地接口(并且它被原始作者使用)。现在我需要找到我询问的机制或扩展所有代码以支持 I/O 上下文。我很幸运,所以我找到了相对简单的方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 2013-06-10
      相关资源
      最近更新 更多