在多线程应用程序中如何重定向 stderr &标准输出在每个线程的单独文件中?

发布于 2024-12-03 14:58:15 字数 767 浏览 1 评论 0原文

我有一个多线程应用程序,在其中创建一个如下所示的线程:

int main(int argc,char *argv[])
{
    pthread_t thread_id[argc-1];
    int i;
    struct parameter thread_data[argc-1];
    int status;
    for(i=0;i<argc-1;i++)
    {
      thread_data[i].ip_filename = argv[i+1];
      strcpy (thread_data[i].op_filename,argv[i+1]);
      strcat (thread_data[i].op_filename,".h264");
    }

    for(i=0;i<argc-1;i++)
    {
      pthread_create (&thread_id[i], NULL , &thread_function, &thread_data[i]);
    }      
}

现在在线程函数中,我想重定向stderr & stdout 在每个线程的一个单独的文件中。 类似于线程日志文件。

我怎样才能这样做呢?

编辑:

线程特定的打印是否可以显示在不同的终端上..?我的意思是,如果有 2 个线程,那么它会打开 2 个终端在不同的终端上打印每个线程的数据。

I have multi thread application in which I'm creating a thread like this:

int main(int argc,char *argv[])
{
    pthread_t thread_id[argc-1];
    int i;
    struct parameter thread_data[argc-1];
    int status;
    for(i=0;i<argc-1;i++)
    {
      thread_data[i].ip_filename = argv[i+1];
      strcpy (thread_data[i].op_filename,argv[i+1]);
      strcat (thread_data[i].op_filename,".h264");
    }

    for(i=0;i<argc-1;i++)
    {
      pthread_create (&thread_id[i], NULL , &thread_function, &thread_data[i]);
    }      
}

Now in the thread function, I want to redirect stderr & stdout in one separate file as per thread. Something like a thread log file.

How can I do so?

Edit:

If thread specific prints can be displayed on different terminal..? I mean if there are 2 threads then it opens 2 terminals & prints each threads data on different terminals.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

偏爱你一生 2024-12-10 14:58:15

如果您真的必须这样做...

首先您需要创建 2 个 pthread_key_t,一个用于 stdout,一个用于 stderr< /代码>。这些可以使用pthread_key_create创建,并且它们必须可以从所有线程访问。我们将它们称为 stdout_keystderr_key

当创建线程时:

FILE *err = ..., *out = ...;
pthread_setspecific(stdout_key, out);
pthread_setspecific(stderr_key, err);

然后在头文件中:

#define stdout (FILE*)pthread_getspecific(stdout_key)
#define stderr (FILE*)pthread_getspecific(stderr_key)
#define printf(...) fprintf(stdout, ##__VA_ARGS__)

然后只需使用:

fprintf(stderr, "hello\n");
fprintf(stdout, "hello\n");
printf("hello\n");

但我不推荐这种方法。

If you really must do this...

First you need to create 2 pthread_key_ts, one for stdout and one for stderr. These can be created using pthread_key_create, and they must be accessable from all threads. Let's call them stdout_key and stderr_key.

When a thread is being created:

FILE *err = ..., *out = ...;
pthread_setspecific(stdout_key, out);
pthread_setspecific(stderr_key, err);

and then in your header file:

#define stdout (FILE*)pthread_getspecific(stdout_key)
#define stderr (FILE*)pthread_getspecific(stderr_key)
#define printf(...) fprintf(stdout, ##__VA_ARGS__)

then just use:

fprintf(stderr, "hello\n");
fprintf(stdout, "hello\n");
printf("hello\n");

I don't recommend this approach though.

冰魂雪魄 2024-12-10 14:58:15

我认为这不可能直接实现。 stdin/stdout 是全局变量,在线程之间共享,文件描述符也是如此。

您必须创建自己的文件,并将 printf 更改为 fprintf

I don't think this is possible directly. stdin/stdout are global variables, shared between threads, and so are file descriptors.

You'll have to create your own files, and change the printf into fprintf.

微暖i 2024-12-10 14:58:15

根据定义,stdoutstderr 是唯一的流。想象一下,如果有多个 stdout,shell 将如何重定向您的流?您需要创建自己的输出流/文件变量并使用它们。这有问题吗?

您可能会发现使用线程特定存储很有用。


您不能使进程在不同的终端上输出某些内容。该进程不知道终端,它只是输出流,然后终端接收它并显示。

然而,您可以做的是将其中一个流的输出定向到文件中,并在不同的终端中运行 tail -f

stdout and stderr are unique streams, by definition. Imagine, how would shell redirect your streams if there were multiple stdouts? You would need to create your own output streams/file variables and use them instead. Is there a problem with that?

You might find it useful to use thread-specific storage.


You cannot make a process output something on a different terminal. The process doesn't know about terminal, it just outputs the stream, and the terminal picks it up and displays.

What you can however do is to direct output from one of the streams into a file, and run tail -f <filename> in a different terminal.

随遇而安 2024-12-10 14:58:15

您必须跟踪每个线程使用的 FILE* / fd 并使用 fprintf 等。没有其他方法。

对于多个终端,您需要在程序中打开每个终端。无法自动确定要打开哪一个。在要打开的终端的 shell 中运行 /bin/tty,然后在程序中打开该终端。

另一种方法是使用 AF_UNIX 套接字侦听连接。然后编写一个连接到该套接字的单独程序。您可以在希望出现输出的终端中运行该程序。

You will have to keep track of what FILE* / fd to use for each thread and use fprintf etc. There's no other way.

For multiple terminals, you need to open each terminal in your program. There's no way to automatically figure out which one to open. Run /bin/tty in the shell of the terminal you want to open, and then open that terminal in your program.

An alternative method would be to have a AF_UNIX socket listening for connections. Then you write a separate program which connects to that socket. You could run that program in the terminal where you wish output to appear.

肤浅与狂妄 2024-12-10 14:58:15

我在线程内使用 fork() 来重定向分叉进程的标准输出,而“true”线程位于 waitpid() 中。
问题是如何将文件传递到要重定向标准输出的位置。
我使用全局线程池,线程会通过pthread_equal(pthread_self(),iterator)找到自己,然后在全局线程池结构中有一个outfile,程序应该在其中重定向stdout。
在我的例子中,我创建了一个 tmpnam() 并将其写入线程结构,但您可以按照自己的意愿使用它。

这是一些示例代码:(即时编写)

pthread_t *t_cur=NULL;
int i,pid,newout;
char *outfile=NULL;

for(i=0;i<MAX_THREADS;i++)
  if(pthread_equal(pthread_self(),globals.tpool[i]->thread))
    break;
if(i==MAX_THREADS)
{
   printf("cannot find myself into global threads pool.\n");
   pthread_exit(&i);
 }
if(globals.tpool[i]->outfile == NULL) //  redirect stdout only if outfile is not set ( this is specfic for my purposes )
{
  outfile = globals.tpool[i]->outfile = malloc(L_tmpnam*sizeof(char));
  tmpnam(outfile);
}

if((pid = fork()) == 0)
{
   if(outfile!=NULL)
   {
     newout = open(outfile,O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
     dup2(newout,STDOUT_FILENO);
     close(newout);
   }
   /* your code here */
}
else
  waitpid(pid,NULL);
pthread_exit(&i);

我确实是即时编写的,我尚未测试此代码,因此请注意修复任何错误。由于调用我自己的库,我没有发布我的真实代码。这里我没有检查 tmpnam()fork()open()malloc()< 的返回值/code>,你应该这样做。

I use a fork() inside the thread for redirect the stdout of the forked process while the "true" thread is in waitpid().
The problem is how to pass the file where you want to redirect stdout.
I use a global thread pool, and the thread will find itself through pthread_equal(pthread_self(),iterator), then in the global thread pool structure there is the outfile where the program should redirect the stdout.
In my case I create a tmpnam() and write it to the thread struct, but you can use it how you wish.

Here is some example code: (written on the fly)

pthread_t *t_cur=NULL;
int i,pid,newout;
char *outfile=NULL;

for(i=0;i<MAX_THREADS;i++)
  if(pthread_equal(pthread_self(),globals.tpool[i]->thread))
    break;
if(i==MAX_THREADS)
{
   printf("cannot find myself into global threads pool.\n");
   pthread_exit(&i);
 }
if(globals.tpool[i]->outfile == NULL) //  redirect stdout only if outfile is not set ( this is specfic for my purposes )
{
  outfile = globals.tpool[i]->outfile = malloc(L_tmpnam*sizeof(char));
  tmpnam(outfile);
}

if((pid = fork()) == 0)
{
   if(outfile!=NULL)
   {
     newout = open(outfile,O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
     dup2(newout,STDOUT_FILENO);
     close(newout);
   }
   /* your code here */
}
else
  waitpid(pid,NULL);
pthread_exit(&i);

I really wrote it on the fly, I haven't tested this code, so take care to fix any errors. I didn't post my real code because of calls to my own library. Here I didn't check the return values from tmpnam(), fork(), open() and malloc(), which you should do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文