ulimit 스택 크기 - 프로세스별 또는 스레드별 제한?

ulimit 스택 크기 - 프로세스별 또는 스레드별 제한?

스택 공간이 부족한 Solaris에 프로그램이 있습니다.

이 문제를 조사하는 동안 스택의 ulimit가 무엇인지 간략하게 살펴보았습니다.

user@solaris-box:~$ ulimit -a
...
stack size              (kbytes, -s) 8192

따라서 스택 크기는 8MB로 제한됩니다. 그러나 이것이 프로세스의 한계입니까?

내 프로세스에 10개의 스레드가 있고 각 스레드에 819k만 허용되면 어떻게 되나요? (또는 이들의 조합으로 최대 8MiB까지 가능합니까?)

이에 대한 문서를 찾을 수 없습니다.

답변1

일반화하다

메인 스레드의 경우 호출해야 합니다 setrlimit()(아마도 를 사용하여 ulimit).앞으로이 프로세스는 더 큰 스택 크기가 유효한지 확인하기 위해 시작됩니다.

프로세스가 시작된 스레드의 경우 사용해야 합니다.pthread_attr_setstacksize()스레드 스택 크기는 stack size/의 리소스 제한에 전혀 영향을 받지 않기 때문입니다.setrlimit()getrlimit()

코드는 다음과 같아야 합니다.

pthread_attr attr;
pthread_attr_init( &attr );

// 32MB stack size example - should **NOT** hardcode this
// but get it from an environment variable or property setting
size_t stacksize = 32UL * 1024UL * 1024UL;
pthread_attr_setstacksize( &attr, stacksize );

pthread_create( &tid, &attr, start_func, thread_arg );

현재 스택 크기 제한에서 스레드 스택 크기를 얻을 수 있습니다.

struct rlimit limits;

getrlimit( RLIMIT_STACK, &limits );
size_t stacksize = limits.rlim_cur; // use rlim_max for hard limit

(자체 스레드를 생성하는 라이브러리를 사용하는 경우 해당 라이브러리에는 OpenMPI와 같이 스레드 스택 크기를 설정하는 문서화된 자체 방법이 있을 수 있습니다.)

자세한 답변

리소스 제한은 명령줄을 통해 설정됩니다.ulimit유틸리티.

달리면 truss -f -a -vall -o /tmp/truss.out /usr/bin/ulimit -a보인다

address space limit (kbytes)   (-M)  unlimited
core file size (blocks)        (-c)  unlimited
cpu time (seconds)             (-t)  unlimited
data size (kbytes)             (-d)  unlimited
file size (blocks)             (-f)  unlimited
locks                          (-x)  not supported
locked address space (kbytes)  (-l)  not supported
message queue size (kbytes)    (-q)  not supported
nice                           (-e)  not supported
nofile                         (-n)  1024
nproc                          (-u)  29995
pipe buffer size (bytes)       (-p)  5120
max memory size (kbytes)       (-m)  not supported
rtprio                         (-r)  not supported
socket buffer size (bytes)     (-b)  5120
sigpend                        (-i)  128
stack size (kbytes)            (-s)  8192
swap size (kbytes)             (-w)  not supported
threads                        (-T)  not supported
process size (kbytes)          (-v)  unlimited

조사해보면 /tmp/truss.out알 수 있을 것이다.

7752:   execve("/usr/bin/ulimit", 0xFFFF80FFBFFFF9E8, 0xFFFF80FFBFFFFA00)  argc = 2
7752:    argv: /usr/bin/ulimit -a
7752:   sysinfo(SI_MACHINE, "i86pc", 257)       = 6

  much deleted extraneous data (loading shared libraries, etc)...

7752:   getrlimit(RLIMIT_VMEM, 0xFFFF80FFBFFFD4B0)  = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_CORE, 0xFFFF80FFBFFFD4B0)  = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_CPU, 0xFFFF80FFBFFFD4B0)   = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_DATA, 0xFFFF80FFBFFFD4B0)  = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_FSIZE, 0xFFFF80FFBFFFD4B0) = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_NOFILE, 0xFFFF80FFBFFFD4B0)    = 0
7752:       cur = 1024  max = 65536
7752:   sysconfig(_CONFIG_CHILD_MAX)            = 29995
7752:   pathconf("/", _PC_PIPE_BUF)         = 5120
7752:   pathconf("/", _PC_PIPE_BUF)         = 5120
7752:   sysconfig(_CONFIG_SIGQUEUE_MAX)         = 128
7752:   getrlimit(RLIMIT_STACK, 0xFFFF80FFBFFFD4B0) = 0
7752:       cur = 8388608  max = RLIM64_INFINITY
7752:   getrlimit(RLIMIT_VMEM, 0xFFFF80FFBFFFD4B0)  = 0
7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
7752:   write(1, " a d d r e s s   s p a c".., 942) = 942

ulimit우리는 사용하는 것을 본다getrlimit()(및) 라이브러리 setrlimit()기능리소스 제한을 가져오거나 설정합니다.

모든이 페이지getrlimit()setrlimit() man(굵은 부분 참고):

RLIMIT_STACK

프로세스 스택의 최대 크기(바이트)입니다. 시스템은 이 제한을 초과하여 스택을 자동으로 늘리지 않습니다.

프로세스 내에서 setrlimit()스택 크기 제한은 증가하지만 현재 메모리 세그먼트는 해당 증가를 허용하도록 이동되지 않습니다. 프로세스 스택이 한계까지 증가할 수 있도록 하려면새로운 스택 크기를 사용하려면 프로세스를 실행하기 전에 제한을 변경해야 합니다..

멀티스레드 프로세스에서는setrlimit()호출 스레드가 기본 스레드가 아닌 경우 호출 스레드의 스택 크기 제한에는 영향이 없습니다.. setrlimit()for 에 대한 호출은 RLIMIT_STACK메인 스레드의 스택에만 영향을 미치며, 메인 스레드에서만 이루어져야 합니다(있는 경우).

신호가 SIGSEGV프로세스로 전송됩니다. 프로세스가 SIGSEGV를 유지 또는 무시하거나 캡처 중이지만 SIGSEGV아직 대체 스택 사용을 예약하지 않은 경우(참고자료 참조 sigaltstack(2)) 처리는 보내기 전에 로 SIGSEGV설정됩니다 .SIG_DFL

따라서 메인 스레드가 아닌 다른 프로세스에서 생성된 스레드의 스택 크기는 RLIMIT_STACK프로세스 리소스 제한의 영향을 받지 않습니다. 전화해야 해setrlimit() 앞으로더 큰 스택 크기 제한이 실제로 적용되는지 확인하기 위해 프로세스가 상위 프로세스에서 시작됩니다.

모든매뉴얼 pthread_create()페이지:

생성된 새 스레드는 pthread_create()속성에 지정된 스택을 사용하며 stackaddr스택은 속성에 지정된 바이트 수 동안 지속됩니다 stacksize. 기본적으로 스택 크기는 32비트 프로세스의 경우 1MB이고 64비트 프로세스의 경우 2MB입니다(바라보다pthread_attr_setstacksize(3C)). stackaddrstacksize속성 모두에 기본값이 사용되는 경우 pthread_create()32비트 프로세스의 경우 최소 1MB, 64비트 프로세스의 경우 2MB인 새 스레드에 대한 스택이 생성됩니다. (사용자 정의 스택 크기에 대한 설명을 참조하세요).

...

노트

...

사용자가 지정한 스택 크기는 값보다 커야 합니다 PTHREAD_STACK_MIN. 최소 스택 크기는 사용자 스레드 함수의 스택 프레임을 수용하지 못할 수 있습니다 start_func. 스택 크기가 지정된 경우 start_func최소 요구 사항 외에도 호출할 수 있는 요구 사항과 기능도 충족해야 합니다.

스레드의 런타임 스택 요구 사항을 결정하는 것은 종종 어렵습니다. PTHREAD_STACK_MIN.txt 파일을 실행하는 데 필요한 스택 저장 공간의 양을 지정합니다 NULL start_func. 스택 저장소에 대한 전체 런타임 요구 사항은 런타임 연결을 수행하는 데 필요한 저장소와 printf()스레드에서 호출하는 라이브러리 런타임에 필요한 저장소 양(예:)에 따라 달라집니다. 이렇게 저장된 매개변수는 프로그램이 실행될 때까지 알 수 없으므로 기본 스택을 사용하는 것이 가장 좋습니다. 런타임 요구 사항을 알고 있거나 기본값보다 더 큰 스택을 사용하기로 결정한 경우 직접 지정하는 것이 좋습니다.

관련 정보