2010-05-19 30 views
0

对于不同的POSIX线程,有没有可能为printf(3)等标准输出实现不同的重定向?标准输入怎么样?每个POSIX线程有不同的标准流

我有很多基于标准输入/输出的代码,我只能将此代码分离到不同的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; 
} 

回答

4

如果您使用clone创建线程,则可以执行所需操作,但POSIX.1指出线程必须共享打开的文件描述符。

有几个技巧你可以尝试,但你真的应该将呼叫转换为接受函数的参数FILE *

+0

真的很好的一点技术上能够解决原来的任务,但在我分析情况更深之后,我更愿意重做代码,因为我打算将来重用它,我不想引入任何看起来像fork()的东西(是的,这超出了原始问题)。 – 2010-05-20 06:42:46

0

如果你坚持使用标准I /像O功能的“printf()”,那么我能想到的,可以这样做的唯一途径是标准I/O库,支持线程特定使用线程本地数据结构的I/O(类似于“errno”是调用返回线程本地错误号的函数的宏)。我不知道任何标准I/O的实现。

+0

是的,我需要某种方式来执行此类线程本地标准I/O重定向。原始代码是从VxWorks移植过来的,而且这个操作系统有类似这样的东西的原生界面(原来的作者使用它)。现在我需要找到所需的机制,或者扩展所有代码以支持I/O上下文。我很幸运,所以我找到了比较简单的方法。 – 2010-05-20 06:49:01

1

在* nix系统上,文件描述符上的stdio层和文件描述符对进程是全局的。因此,在没有改变的东西的情况下,没有办法做到你想要的。你最好的选择是用fprintf()重写代码。由于这涉及到向arglist添加参数,我甚至不确定是否可以使用预处理器欺骗来实现目标,而无需修改实际代码。

也许你可以澄清你无法创建新进程的原因?这个问题可以从这个角度来解决。所有你打算使用其他stdio函数

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

,同样:

1

如果你有线程本地存储,你可以做这样的事情。当然,最好不要尝试重新定义相同的名称,而是在源文件上执行搜索和替换以使用替代名称。

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

+0

实际上线程本地存储最终用于原始案例,但我反对全球printf重载,因为这可能会产生不可预知的影响。我留在基于线程本地存储的最小重写接口和内部隐藏上下文中。这提供了兼容的界面和良好的工作解决方案。限制是每个客户端线程的一种上下文,对我来说是可以接受的。 – 2010-07-27 19:19:33