스택 공간이 부족한 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()
속성에 지정된 스택을 사용하며stackaddr
스택은 속성에 지정된 바이트 수 동안 지속됩니다stacksize
. 기본적으로 스택 크기는 32비트 프로세스의 경우 1MB이고 64비트 프로세스의 경우 2MB입니다(바라보다pthread_attr_setstacksize(3C)
).stackaddr
및stacksize
속성 모두에 기본값이 사용되는 경우pthread_create()
32비트 프로세스의 경우 최소 1MB, 64비트 프로세스의 경우 2MB인 새 스레드에 대한 스택이 생성됩니다. (사용자 정의 스택 크기에 대한 설명을 참조하세요)....
노트
...
사용자가 지정한 스택 크기는 값보다 커야 합니다
PTHREAD_STACK_MIN
. 최소 스택 크기는 사용자 스레드 함수의 스택 프레임을 수용하지 못할 수 있습니다start_func
. 스택 크기가 지정된 경우start_func
최소 요구 사항 외에도 호출할 수 있는 요구 사항과 기능도 충족해야 합니다.스레드의 런타임 스택 요구 사항을 결정하는 것은 종종 어렵습니다.
PTHREAD_STACK_MIN
.txt 파일을 실행하는 데 필요한 스택 저장 공간의 양을 지정합니다NULL
start_func
. 스택 저장소에 대한 전체 런타임 요구 사항은 런타임 연결을 수행하는 데 필요한 저장소와printf()
스레드에서 호출하는 라이브러리 런타임에 필요한 저장소 양(예:)에 따라 달라집니다. 이렇게 저장된 매개변수는 프로그램이 실행될 때까지 알 수 없으므로 기본 스택을 사용하는 것이 가장 좋습니다. 런타임 요구 사항을 알고 있거나 기본값보다 더 큰 스택을 사용하기로 결정한 경우 직접 지정하는 것이 좋습니다.