2010-12-06 56 views
5
  1. ulimit -s <value>和Linux實現(或任何操作系統)中堆棧大小(線程級別)之間的關係是什麼?堆棧限制和線程之間的關係

    <number of threads> * <each thread stack size>必須小於< stack size assigned by ulimit command>有效的理由?

  2. 在下面的程序中 - 每個線程分配char [PTHREAD_STACK_MIN]並創建10個線程。但是當ulimit被設置爲10 * PTHREAD_STACK_MIN時,它不會因爲中止而導致內核崩潰。對於stacksize的一些隨機值(遠小於10 * PTHREAD_STACK_MIN),它是核心轉儲。爲什麼這樣?

我的理解是stacksize表示堆棧中所有線程在求和過程中佔用的堆棧。

線程函數

#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泛型#48的Ubuntu SMP星期三年11月24十時14分11秒UTC 2010 x86_64的GNU/Linux的

回答

5

在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屬性並詢問系統爲您提供的堆棧大小。

-1

在某個線程程序,所有線程堆棧(除了初始的一個)是從堆中分配,因此RLIMIT_STACK與您的線程可以使用多少堆棧空間幾乎沒有關係。

+0

實際上,在UN * X上,堆棧默認通過`mmap(...,MAP_ANON | MAP_PRIVATE,...)分配,因此地址空間不相交的部分,而不是普通的部分(連續的內存,並通過`sbrk`)進程堆增長。如果您在調用`pthread_create()`之前手動創建了一個具有適當初始化值的`pthread_attr_t`,您可以選擇將一個線程堆棧放入堆中,但這很危險 - 堆棧溢出會簡單地破壞進程堆而不是運行到通常會在堆棧底部顯示未映射的redzone。 – 2010-12-06 17:53:47

+0

@FrankH是的,這是真的;我過於鬆散地使用「堆」。 – 2010-12-06 17:55:22