2016-08-14 3 views
2

나는 clone 콜을 들여다 보았고, 나는 다른 자식 스레드 스택 할당에 대해 세 가지 다른 결과를 발견했다. 다음 데모는 스택을 할당합니다. n -bytes big n이 인수로 전달 된 다음 복제를 시도합니다.Linux 클론 호출의 최소 스택 크기는 무엇입니까?

foo.c를 :시키고 말았다

$ cc -o foo foo.c 
$ ./foo 0 
Segmentation fault 
$ ./foo 23 
Segmentation fault 
$ ./foo 24 
success 
$ ./foo 583 
success 
$ ./foo 584 
success 
carpe momentum 
$ ./foo 1048576 #1024 * 1024, amount suggested by man-page example 
success 
carpe momentum 

0에서 23 사이의 샘플의 겉 핥기의 모든

, 24 사이의 모든 샘플에 대한 : 여기

#define _GNU_SOURCE 
#include <stdlib.h> 
#include <unistd.h> 
#include <sched.h> 
#include <errno.h> 

int child(void *arg) 
{ 
    (void)arg; 
    write(STDOUT_FILENO, "carpe momentum\n", 15); 
    return 0; 
} 

int main(int argc, char **argv) 
{ 
    long stacksize; 
    pid_t pid; 
    void *stack; 

    if (argc < 2) 
     return 1; 

    errno = 0; 
    stacksize = strtol(argv[1], NULL, 0); 
    if (errno != 0) 
     return 1; 

    stack = malloc(stacksize); 
    if (stack == NULL) 
     return 1; 

    pid = clone(child, stack + stacksize, 0, NULL); 
    if (pid == -1) 
     return 1; 

    write(STDOUT_FILENO, "success\n", 8); 

    return 0; 
} 

내 관찰이다 583 부모는 성공했지만 그 어린이는 침묵했다. 584 이상으로 합리적인 것이라면 모두 성공할 수 있습니다.

분해는 child이 스택 공간을 16 바이트 만 사용하고 적어도 16 개 이상을 추가로 사용하여 write을 호출 할 것을 제안합니다. 하지만 그것은 이미 segfaulting을 중지하는 데 필요한 24 바이트 이상입니다.

$ objdump -d foo 
# ... 
080484cb <child>: 
80484cb:  55      push %ebp 
80484cc:  89 e5     mov %esp,%ebp 
80484ce:  83 ec 08    sub $0x8,%esp 
80484d1:  83 ec 04    sub $0x4,%esp 
80484d4:  6a 0f     push $0xf 
80484d6:  68 50 86 04 08   push $0x8048650 
80484db:  6a 01     push $0x1 
80484dd:  e8 be fe ff ff   call 80483a0 <[email protected]> 
80484e2:  83 c4 10    add $0x10,%esp 
80484e5:  b8 00 00 00 00   mov $0x0,%eax 
80484ea:  c9      leave 
80484eb:  c3      ret 
# ... 

이렇게하면 몇 가지 중복되는 질문이 표시됩니다.

  • clone은 24 ~ 583 바이트의 스택을 분할합니까?
  • child은 스택이 너무 적 으면 자동으로 실패합니다.
  • 스택 공간이 모두 무엇에 사용됩니까?
  • 24 및 584 바이트의 의미는 무엇입니까? 서로 다른 시스템 및 구현 방식에 따라 어떻게 다릅니 까?
  • 최소 스택 요구 사항을 계산할 수 있습니까? 해야합니까?

내가는 i686 데비안 시스템에 오전 :

$ uname -a 
Linux REDACTED 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) i686 GNU/Linux 
+0

흥미로운 관찰이지만 많은 질문이 내게 발생합니다. OS는 무엇입니까? CPU 아키텍처? 컴파일러? 32 또는 64 비트? 플래트 홈에있는 작은 다름을 시도 했습니까? 근본적인 차이점? 재미있는 사실 : 30 년 전 썬 마이크로 시스템즈 C 컴파일러에서 100 % 재현성있는 버그를 발견했고 그들은 나를 믿지 않았습니다. * "오류 메시지와 대화하십시오." –

+0

@PeterRowell은'uname'을 질문에 출력했습니다. 감사. 나는 다른 어떤 체계에 그것을 시도하지 않았다. – nebuch

답변

2
  • 이유는 segfault 스택의 24 개 583 바이트 사이에 복제하지 않는 이유는 무엇입니까?

그렇지만 별도의 프로세스이기 때문에 표시되지 않습니다. 24 세 전에, 아이를 세우려고 시도하는 것은 아이를 세우는 것이 아니라 부모에게 세우는 것입니다. strace -ff를 사용하여이 문제를 확인하십시오.

  • 스택이 너무 적 으면 자식이 자동으로 실패합니다.

자녀가 사망하면 부모에게 통지됩니다. 이 경우 부모 (clone() 호출을 수행하는 부모)는이 알림으로 아무 것도하지 않습니다. 24 미만의 "침묵"이 아닌 이유는 그것이 부모가 사망하고 그 경우 쉘이 통지를받을 것이기 때문입니다.

  • 사용되는 스택 공간은 모두 무엇입니까?
  • 24 및 584 바이트의 의미는 무엇입니까? 서로 다른 시스템 및 구현 방식에 따라 어떻게 다릅니 까?

제 24 (및 비트) child에 함수 호출을 설정하기 위해 사용된다. 이것은 정상적인 함수이기 때문에 완료되면 호출하는 함수로 돌아갑니다. 이는 clone이 반환 할 호출 함수를 설정해야한다는 것을 의미합니다 (자식을 정상적으로 종료하는 호출 함수).

584 (및 비트)는 호출 함수, 함수, writewrite이 호출하는 지역 변수에 필요한 메모리 양입니다. 가능하고 방에서 실행할 때 clone 또는 child 학대입니다 stack 전에 메모리의 비트가있을 수 있기 때문에

내가 작성하는 이유 "(와 비트)"입니다. 클론 이후에 free(stack)을 추가하여 악용 사례를 확인하십시오.

  • 나는 최소 스택 요구 사항을 계산할 수 있습니까? 해야합니까?

일반적으로 그렇게하지 않아야합니다. 그것은 당신의 기능과 그것들이 사용하는 외부 기능에 대한 꽤 깊은 분석을 필요로합니다. 그냥 "정상적인"프로그램과 마찬가지로, 나는 (정확하게 기억한다면, 리눅스에서는 8MB이다.) 기본값으로 갈 것을 제안한다. 엄격한 메모리 요구 사항 (또는 스택 오버 플로우 문제)이있는 경우에만 이러한 사항에 대해 걱정해야합니다.

+0

'write' 호출에서'child'가 사용하는 584 바이트의 대부분은 무엇입니까? 또한 16 바이트가 아닌 16 바이트를 설정하려면 왜 24 바이트가 필요합니까? – nebuch

+0

@nebuch 아마; 당신이 보여 줬던 것처럼, 아이 자체는별로 사용하지 않습니다. "호출 함수"가이 사용으로 이어질 몇 가지 추가 호출을 수행 할 수도 있지만. 정확히 알아 내기 위해서는 좀 더 디버그해야합니다. – mweerden

+0

엄격한 메모리 요구 사항이 있다고 가정하면, 호출 트리 또는 이와 유사한 것에서 최대 스택 깊이를 계산하는 방법이 있습니까? – nebuch