2013-03-04 5 views
1

Я пытаюсь отладить некоторый код относительно использования стека. Я сделал следующую тестовую программу (просто как пример, чтобы выяснить, как PTHREAD библиотека работает):Как я могу решить, сколько стека я могу использовать после вызова pthread_attr_setstacksize?

#include <string.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <limits.h> 
#include <stdio.h> 

static void *threadFunc1(void *arg) 
{ 
    char arr[5000]; 
    printf("Hello fromt threadFunc1 address of arr:%p\n", &arr); 
    return; 
} 

static void *threadFunc2(void *arg) 
{ 
    char arr[10000]; 
    printf("Hello fromt threadFunc2 adress of arr:%p\n", &arr); 
    return; 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t t1,t2; 
    pthread_attr_t thread_attr; 
    void *res; 
    int s; 
    size_t tmp_size=0; 
    s=pthread_attr_init(&thread_attr); 
    assert(s==0); 
    s=pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN); 
    assert(s==0); 
    s=pthread_attr_getstacksize(&thread_attr , &tmp_size); 
    assert(s==0); 
    printf("forced stack size of pthread is:%zd\n", tmp_size); 
    printf("sizeof char is %zd\n", sizeof(char)); 

    s = pthread_create(&t1, &thread_attr, threadFunc1, NULL); 
    assert(s==0); 
    sleep(1); 
    s = pthread_create(&t2, &thread_attr, threadFunc2, NULL); 
    assert(s==0); 
    sleep(1); 

    printf("Main done()\n"); 
    exit(0); 
} 

Когда я исполняю его я получаю следующий результат (на моих x86_64 Ubuntu):

forced stack size of pthread is:16384 
sizeof char is 1 
Hello fromt threadFunc1 address of arr:0x7fef350d3b50 
Segmentation fault (core dumped) 

Есть ли способ узнать, сколько осталось от запрошенного PTHREAD_STACK_MIN при вводе моего вновь созданного потока? Если я изменяю размер массива char, когда я ввожу функцию потока, кажется, что предел составляет от 7000 до 8000, что я не ожидал (где-то рядом с 16384).

ответ

1

Существует не так много «хороших» вещей, которые могут возникать при игре с размерами стека ниток. Обычно, когда это происходит, это происходит потому, что кто-то пытается создать сотни (или тысячи) потоков и работать в пределах процесса. Как правило, это не очень хороший способ использования потоков. Пример: создание нового потока для каждого входящего запроса на подключение к серверу.

Даже если это не то, о чем вы просите, несколько вещей, которые вы должны знать.

В производственном (реальном мире) кодексе, а не на простом примере, вы никогда не можете быть уверены в том, что определенный «уменьшенный» размер стека в потоке на 100% безопасен. Вы можете тщательно протестировать его при заданном размере стека, а затем, возможно, после того, как вы убедитесь в своей тестовой среде, что он «достаточно большой», возможно, немного увеличьте его (возможно, 10-15%) для использования в производстве. Я не знаю каких-либо конкретных инструментов, которые могут рассказать вам о максимальном использовании стека в потоке во время выполнения. Лучше избегать этого полностью.

Уменьшение размера стека за потоки не приведет к сокращению потребления памяти напрямую или к повышению производительности. Вы не оптимизируете свой код, экспериментируя с этим.

Гораздо безопаснее использовать размер стека по умолчанию, выбранный локальной реализацией, когда вы можете, пока у вас нет реальной причины изменить его.

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

Слегка модифицированная версия кода, который работает здесь:

#include <stdio.h> 
#include <string.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <unistd.h> 
#include <limits.h> 

static void *threadFunc1(void *arg) 
{ 
    char arr[5000]; 
    printf("Hello fromt threadFunc1\n"); 
    return NULL; 
} 

static void *threadFunc2(void *arg) 
{ 
    char arr[10000]; 
    printf("Hello fromt threadFunc2\n"); 
    return NULL; 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t t1,t2; 
    pthread_attr_t thread_attr; 
    int s = 0; 
    size_t tmp_size=0; 

    s = pthread_attr_init(&thread_attr); 
    assert(s==0); 

    s = pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN + 0x1000); 
    assert(s==0); 

    s = pthread_attr_getstacksize(&thread_attr , &tmp_size); 
    assert(s==0); 

    printf("forced stack size of pthread is:%zu\n", tmp_size); 

    s = pthread_create(&t1, &thread_attr, threadFunc1, NULL); 
    assert(s==0); 

    sleep(1); /* not the "right" way, but ok for a quick test */ 

    s = pthread_create(&t2, &thread_attr, threadFunc2, NULL); 
    assert(s==0); 

    sleep(1); 

    printf("Main done()\n"); 
    return 0; 
} 

Примечание: Я использовал

$ gcc -O0 -Wall stack_t.c -o stack_t -pthread 
./stack_t 

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

EDIT: приведенный выше пример добавляет значение к минимуму в качестве примера его увеличения. Возможно, вам придется добавить еще больше. Если 0x1000 недостаточно, попробуйте 0x2000, 0x3000 и т. Д., Пока не найдете тот, который работает. Как вы обнаружили, сокращение размера стека потоков является сложным и может также зависящим от платформы. Вот почему у меня есть предупреждения выше о том, что это небезопасно.

+0

Меня не интересует выполнение определенного количества потоков или ограничение использования памяти. Мне было просто любопытно, могу ли я уменьшить размер стека по умолчанию для потока, чтобы узнать, перекосил ли мой код.Код, который я хотел запустить, не запускается на linux вообще в моей производственной среде, поэтому я хочу привести простой пример в качестве иллюстрации. – kungjohan

+0

Если я правильно вас понимаю, вы хотите уменьшить размер стека потоков, просто чтобы узнать, когда он «сломается»? Это может варьироваться в зависимости от кода, наборов данных и т. Д. О том, что вы можете сделать, это экспериментировать с уменьшенными размерами стека и запускать множество тестовых примеров с различными наборами данных, аргументами командной строки, взаимодействиями пользователей и т. Д. (В зависимости от на что работает настоящая программа) и найти, что ломается. Вот почему размеры стандартных стеков обычно устанавливаются довольно высокими в большинстве реализаций, чтобы избежать необходимости проходить этот процесс. –

+0

Да, это для отладки кода, который будет работать на другой платформе с ограниченной памятью. Я точно знаю, какие тесты я хочу запустить, но я не знаю, как установить точный размер стека, который я хочу проверить. – kungjohan