Я работаю с FreeRTOS (newlib) в небольшой встроенной системе и обнаружил, что printf и семейство тратят огромное количество места в стеке. У меня много задач, и мне не хватает оперативной памяти, чтобы сделать стек для каждой достаточно большим, чтобы поддерживать вызовы printf(). Чтобы обойти это, я работаю над созданием задачи «сервер печати», которая будет иметь большой стек и выполнять все функции printf() от имени других задач.
Итак, мой вопрос: как правильно передать va_list в другой поток (задачу)? В приведенном ниже примере создаются параметры мусора.
Коротко о том, как это работает: task_printf() поместит свои параметры в статические переменные, а затем даст сигнал server_task выполнить реальную печать. Когда server_task выполнена, это сигнализирует клиенту о продолжении.
// printf parameters
static va_list static_args;
static const char *static_format;
static int static_result;
// printf server task. Processes printf requests forever
void server_task(void *pvParameters)
{
while(1)
{
xSemaphoreTake(printf_start, portMAX_DELAY); // wait for start command
static_result = vprintf(static_format, static_args);
xSemaphoreGive(printf_finished); // give finish signal
}
}
// get server task to print something for us
int task_printf(const char *format, ...)
{
int result;
xSemaphoreTake(printf_mutex, portMAX_DELAY); // lock
va_start(static_args, format);
static_format = format;
xSemaphoreGive(printf_start); // give start signal
xSemaphoreTake(printf_finished, portMAX_DELAY); // wait for completion
va_end(static_args);
...
}