Связь между пределом стека и потоками - PullRequest
6 голосов
/ 06 декабря 2010
  1. Какова взаимосвязь между ulimit -s <value> и размером стека (на уровне потока) в реализации Linux (или, если уж на то пошло, любой ОС)?

    <number of threads> * <each thread stack size> должно быть меньше, чем < stack size assigned by ulimit command> допустимое обоснование?

  2. В приведенной ниже программе - каждый поток выделяет символ [PTHREAD_STACK_MIN] и создается 10 потоков.Но когда для ulimit установлено значение 10 * PTHREAD_STACK_MIN, он не выполняет coredump из-за прерывания.При некотором случайном значении размера стека (гораздо меньшем, чем 10 * PTHREAD_STACK_MIN), он генерирует дамп памяти.Почему так?

Мое понимание состоит в том, что размер стека представляет стек, занятый всеми потоками при суммировании для процесса.

Функция потока

#include <cstdio>  
#include <error.h>  
#include <unistd.h>  
#include <sys/select.h>  
#include <sys/time.h>  
#include <sys/resource.h>  
using namespace std;        
#include <pthread.h>  
#include <bits/local_lim.h>  

const unsigned int nrOfThreads = 10;  
pthread_t  ntid[nrOfThreads];


void* thr_fn(void* argv)
{
    size_t _stackSz;  
    pthread_attr_t _attr;  
    int err;

    err = pthread_attr_getstacksize(&_attr,&_stackSz);
    if( 0 != err)
    {
        perror("pthread_getstacksize");
    }

    printf("Stack size - %lu, Thread ID - %llu, Process Id - %llu \n", static_cast<long unsigned int> (_stackSz), static_cast<long long unsigned int> (pthread_self()), static_cast<long long unsigned int> (getpid()) );


    //check the stack size by actual allocation - equal to 1 + PTHREAD_STACK_MIN
    char a[PTHREAD_STACK_MIN ] = {'0'};

    struct timeval tm;
    tm.tv_sec = 1;
    while (1)
        select(0,0,0,0,&tm);

    return ( (void*) NULL);
} 

Основная функция

int main(int argc, char *argv[])

{  

    struct rlimit rlim;
    int err;

    err = getrlimit(RLIMIT_STACK,&rlim);
    if( 0 != err)
    {
        perror("pthread_create ");
        return -1;
    }

    printf("Stacksize hard limit - %ld, Softlimit - %ld\n", static_cast <long unsigned int> (rlim.rlim_max) , 
            static_cast <long unsigned int> (rlim.rlim_cur));

    for(unsigned int j = 0; j < nrOfThreads; j++)
    {
        err = pthread_create(&ntid[j],NULL,thr_fn,NULL);
        if( 0 != err)
        {
            perror("pthread_create ");
            return -1;
        }
    }

    for(unsigned int j = 0; j < nrOfThreads; j++)
    {
        err = pthread_join(ntid[j],NULL);
        if( 0 != err)
        {
            perror("pthread_join ");
            return -1;
        }
    }

    perror("Join thread success");

    return 0;
}

PS:
Я использую версию Ubuntu 10.04 LTS, со спецификацией ниже.
Ноутбук Linux 2.6.32-26-generic # 48-Ubuntu SMP Ср 24 ноября 10:14:11 UTC 2010 x86_64 GNU / Linux

Ответы [ 2 ]

6 голосов
/ 06 декабря 2010

В UNIX / Linux getrlimit(RLIMIT_STACK) гарантирует только размер стека основного потока.Ссылка OpenGroup является явной для этого «стека исходного потока»:

http://www.opengroup.org/onlinepubs/009695399/functions/getrlimit.html

Для Linux есть ссылка, которая указывает, что RLIMIT_STACK - это то, что будет использоваться по умолчанию для любогостек потоков (для потоков NPTL):

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html

Как правило, поскольку программист может решить (используя нестандартные атрибуты при создании потока), куда поместить стек и / или сколькостек, используемый для нового потока, не существует такого понятия, как «совокупный лимит стека процессов».Это скорее получается из общего размера RLIMIT_AS адресного пространства.
Но у вас есть ограничение на количество потоков, которое вы можете создать, sysconf(PTHREAD_THREADS_MAX), и у вас есть нижний предел для минимального размера стека потоковдолжен иметь, sysconf(PTHREAD_STACK_MIN).

Кроме того, вы можете запросить размер стека по умолчанию для новых потоков:

pthread_attr_t attr;
size_t stacksize;
if (!pthread_attr_init(&attr) && !pthread_attr_getstacksize(&attr, &stacksize))
    printf("default stacksize for a new thread: %ld\n", stacksize);

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

0 голосов
/ 06 декабря 2010

В многопоточной программе стеки для всех потоков (кроме начального) выделяются из кучи, поэтому RLIMIT_STACK практически не имеет отношения к тому, сколько стекового пространства вы можете использовать для своих потоков.

...