Различные стандартные потоки на поток POSIX - PullRequest
0 голосов
/ 19 мая 2010

Есть ли возможность добиться разных перенаправлений для стандартного вывода, таких как 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 ]

4 голосов
/ 19 мая 2010

Вы можете делать, что хотите, если вы создаете потоки, используя clone, но POSIX.1 говорит, что потоки должны совместно использовать открытые файловые дескрипторы.

Есть несколько приемов, которые вы можете попробовать, но вам действительно нужно просто преобразовать вызовы в функции приема аргументов FILE *.

1 голос
/ 26 июля 2010

Если у вас есть локальное хранилище потоков, вы можете сделать что-то вроде:

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

и аналогично для всех других функций stdio, которые вы собираетесь использовать. Конечно, было бы лучше не пытаться переопределять те же имена, а вместо этого выполнять поиск и замену исходных файлов, чтобы использовать альтернативные имена.

Кстати, даже без расширений локального хранилища потока для компилятора, вы можете использовать вызов функции, который возвращает право FILE * для использования вызывающим потоком.

1 голос
/ 19 мая 2010

В * nix системах слои stdio над файловыми дескрипторами и файловые дескрипторы являются глобальными для процесса. Таким образом, нет способа сделать то, что вы хотите, не изменив что-то . Лучше всего переписать код с помощью fprintf (). Поскольку это связано с добавлением аргумента в список аргументов, я даже не уверен, что вы сможете использовать хитрость препроцессора для достижения своих целей без изменения реального кода.

Может быть, вы могли бы уточнить причины, по которым вы не можете создавать новые процессы? С этой точки зрения проблема может быть решена.

0 голосов
/ 19 мая 2010

Если вы настаиваете на использовании стандартных функций ввода / вывода, таких как «printf ()», то единственный способ, которым я могу думать о том, что это может быть сделано, - это для стандартной библиотеки ввода / вывода для поддержки потокового ввода / вывода с использованием локальные структуры данных потока (аналогично тому, как "errno" - это макрос, вызывающий функцию, которая возвращает номер локальной ошибки потока). Я не знаю каких-либо реализаций стандартного ввода / вывода, которые делают это.

...