Dans une application multi-thread, comment puis-je redirect stderr & stdout dans un fichier séparé selon le thread?

J’ai une application multi-thread dans laquelle je crée un thread comme celui-ci:

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]); } } 

Maintenant, dans la fonction thread, je veux redirect stderr & stdout dans un fichier séparé selon le thread. Quelque chose comme un fichier journal de thread.

Comment puis-je le faire?

Modifier:

Si des impressions spécifiques à un fil peuvent être affichées sur un autre terminal, ..? Je veux dire que s’il ya 2 threads, il ouvre 2 terminaux et affiche les données de chaque thread sur différents terminaux.

Si vous devez vraiment faire ça …

Vous devez d’abord créer 2 pthread_key_t s, un pour stdout et un pour stderr . Ceux-ci peuvent être créés en utilisant pthread_key_create , et ils doivent être accessibles à partir de tous les threads. Appelons-les stdout_key et stderr_key .

Quand un fil est créé:

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

puis dans votre fichier d’en-tête:

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

puis utilisez simplement:

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

Je ne recommande pas cette approche cependant.

Je ne pense pas que ce soit possible directement. stdin / stdout sont des variables globales, partagées entre les threads, et donc les descripteurs de fichier.

Vous devrez créer vos propres fichiers et changer le printf en fprintf .

stdout et stderr sont des stream uniques, par définition. Imaginez, comment le shell redirectait-il vos stream s’il y avait plusieurs stdout ? Vous devrez créer vos propres stream de sortie / variables de fichier et les utiliser à la place. Y at-il un problème avec ça?

Vous trouverez peut-être utile d’utiliser un stockage spécifique à un thread .


Vous ne pouvez pas faire en sorte qu’un processus produise quelque chose sur un autre terminal. Le processus ne connaît pas le terminal, il sort simplement le stream et le terminal le récupère et l’affiche.

Ce que vous pouvez cependant faire, c’est diriger la sortie de l’un des stream dans un fichier et exécuter tail -f dans un autre terminal.

Vous devrez garder trace de ce que FILE* / fd utiliser pour chaque thread et utiliser fprintf etc. Il n’y a pas d’autre moyen.

Pour plusieurs terminaux, vous devez ouvrir chaque terminal de votre programme. Il n’y a aucun moyen de déterminer automatiquement lequel ouvrir. Exécutez /bin/tty dans le shell du terminal que vous souhaitez ouvrir, puis ouvrez ce terminal dans votre programme.

Une autre méthode serait d’avoir un socket AF_UNIX écoute des connexions. Ensuite, vous écrivez un programme distinct qui se connecte à cette prise. Vous pouvez exécuter ce programme dans le terminal où vous souhaitez que la sortie apparaisse.

J’utilise un fork() dans le thread pour redirect la sortie standard du processus fork() alors que le “vrai” thread est dans waitpid() . Le problème est de savoir comment passer le fichier où vous voulez redirect stdout. J’utilise un pool de threads global, et le thread se trouvera via pthread_equal(pthread_self(),iterator) , puis dans la structure de pool de threads globale se trouve le fichier de sortie vers lequel le programme doit redirect la sortie standard. Dans mon cas, je crée un tmpnam() et l’écris dans la structure du thread, mais vous pouvez l’utiliser comme vous le souhaitez.

Voici un exemple de code: (écrit à la volée)

 pthread_t *t_cur=NULL; int i,pid,newout; char *outfile=NULL; for(i=0;ithread)) 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); 

Je l’ai vraiment écrit à la volée, je n’ai pas testé ce code, alors prenez soin de corriger les erreurs éventuelles. Je n’ai pas posté mon vrai code à cause d’appels vers ma propre bibliothèque. Ici, je n’ai pas vérifié les valeurs de retour de tmpnam() , fork() , open() et malloc() , ce que vous devriez faire.