2010-05-19 15 views
0

Existe-t-il une possibilité de réaliser différentes redirections pour la sortie standard comme printf (3) pour différents threads POSIX? Qu'en est-il de l'entrée standard?Différents flux standard par thread POSIX

J'ai beaucoup de code basé sur l'entrée/sortie standard et je peux seulement séparer ce code en thread différent de POSIX, pas de processus. Système d'exploitation Linux, bibliothèque standard C. Je sais que je peux refactoriser le code pour remplacer printf() par fprintf() et plus loin dans ce style. Mais dans ce cas, je dois fournir un type de contexte que l'ancien code n'a pas.

Donc personne n'a une meilleure idée (regardez dans le code ci-dessous)?

#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; 
} 

Répondre

4

Vous pouvez faire ce que vous voulez si vous créez des unités d'exécution en utilisant clone, mais POSIX.1 indique que les unités d'exécution doivent partager des programmes de fichiers ouverts.

Il y a plusieurs astuces que vous pourriez essayer, mais vous devriez juste convertir les appels à l'argument FILE * acceptant des fonctions.

+0

Vraiment beau point technique capable de résoudre la tâche originale mais après avoir analysé la situation plus profond je préférais retravailler le code car je prévois de le réutiliser dans le futur et je préfère ne rien présenter ressemblant à fork()). –

0

Si vous insistez sur l'utilisation de la norme E/fonctions S comme « printf() » la seule façon dont je peux penser que cela pourrait être fait est pour la bibliothèque E/S standard pour un soutien spécifique fils E/S utilisant des structures de données locales (semblable à la façon dont "errno" est une macro qui appelle une fonction qui renvoie le numéro d'erreur locale du thread). Je ne connais pas d'implémentations d'E/S standard qui le font.

+0

Oui, j'avais besoin d'un moyen de faire une telle redirection d'E/S standard locale. Le code d'origine a été porté à partir de VxWorks et ce système d'exploitation avait une interface native pour ce genre de choses (et il était utilisé par les auteurs originaux). Maintenant, je dois soit trouver la mécanique que j'ai demandé ou étendre tout le code pour prendre en charge le contexte d'E/S. J'ai de la chance, alors j'ai trouvé un moyen relativement facile. –

1

Les systèmes * * nix, les couches stdio sur les descripteurs de fichiers et les descripteurs de fichiers sont globaux pour un processus. Ainsi, il n'y a aucun moyen de faire ce que vous voulez sans changer quelque chose. Votre meilleur pari est de réécrire le code en utilisant fprintf(). Comme cela implique d'ajouter un argument à un arglist, je ne suis même pas sûr que vous seriez capable d'utiliser la supercherie du préprocesseur pour atteindre vos objectifs sans modifier le code réel. Peut-être pourriez-vous clarifier les raisons pour lesquelles vous ne pouvez pas créer de nouveaux processus? Le problème peut être résolu sous cet angle.

1

Si vous avez le stockage local des threads, vous pouvez faire quelque chose comme:

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

et de même pour toutes les autres fonctions stdio que vous voulez utiliser. Bien sûr, il serait préférable de ne pas essayer de redéfinir les mêmes noms, mais plutôt d'effectuer une recherche et un remplacement sur les fichiers sources pour utiliser d'autres noms.

BTW même sans extensions de stockage local au thread du compilateur, vous pouvez utiliser un appel de fonction qui renvoie le droit FILE * pour le thread appelant à utiliser.

+0

En fait le stockage local de thread a été finalement utilisé pour le cas original mais je suis contre la surcharge globale de printf parce que ceci peut avoir des effets imprévisibles. Je suis resté sur l'interface minimalement retravaillée et le contexte caché interne basé sur le stockage local de fil. Cela à la fois fourni une interface compatible et une bonne solution de travail.La limitation est un contexte par thread client qui est acceptable pour moi. –