2016-10-28 5 views
2

컨텍스트 스위칭에 재미가 있습니다. 예제 코드를 파일에 복사했습니다. http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html컨텍스트 스위칭 - 여기 makecontext와 swapcontext가 작동합니까 (OSX)

그리고 OSX 용 _XOPEN_SOURCE 매크로를 정의했습니다. 나에 대한 스왑 컨텍스트가 사용되지, 얻을 수 있도록에서

#define _XOPEN_SOURCE 
#include <stdio.h> 
#include <ucontext.h> 


static ucontext_t ctx[3]; 


static void 
f1 (void) 
{ 
    puts("start f1"); 
    swapcontext(&ctx[1], &ctx[2]); 
    puts("finish f1"); 
} 


static void 
f2 (void) 
{ 
    puts("start f2"); 
    swapcontext(&ctx[2], &ctx[1]); 
    puts("finish f2"); 
} 


int 
main (void) 
{ 
    char st1[8192]; 
    char st2[8192]; 


    getcontext(&ctx[1]); 
    ctx[1].uc_stack.ss_sp = st1; 
    ctx[1].uc_stack.ss_size = sizeof st1; 
    ctx[1].uc_link = &ctx[0]; 
    makecontext(&ctx[1], f1, 0); 


    getcontext(&ctx[2]); 
    ctx[2].uc_stack.ss_sp = st2; 
    ctx[2].uc_stack.ss_size = sizeof st2; 
    ctx[2].uc_link = &ctx[1]; 
    makecontext(&ctx[2], f2, 0); 


    swapcontext(&ctx[0], &ctx[2]); 
    return 0; 
} 

나는 그것을

의 gcc -o 상황에 맞는 context.c -g

winges을 구축 할 수 있습니다. Meh.

실행할 때 그냥 중단됩니다. 그것은 추락하지 않는 것 같습니다. 그냥 달려있다.

나는 gdb를 사용해 보았지만 일단 swapcontext를 사용하면 빈칸이되었다. 그것은 f1로 점프하지 않습니다. 나는 계속해서 엔터를 누르고 콘솔의 새로운 라인으로 커서를 옮기겠습니까?

무슨 일이 일어나는 지 아세요? Mac/deprecate 메소드로 작업하는 것과 관련이 있습니까?

감사

그것은 당신의 코드처럼 보이는

답변

4

은 그냥 복사 /이 좌절가 작동하지 않습니다 확인해야합니다 the ucontext documentation에서 붙여 ... 지금까지 내가 말할 수있는

, 당신의 스택이 너무있다 작은. 스택을 32KiB 미만으로 작동시키지 못했습니다. 이러한 변경을

시도 :

#define STACK_SIZE (1<<15) // 32KiB 

// . . . 

    char st1[STACK_SIZE]; 
    char st2[STACK_SIZE]; 

그래 그것을 해결했습니다. 왜 그것을 고칠 수 있었습니까?

글쎄, 문제를 좀 더 파헤 치자. 첫째, 실제로 진행되고있는 것을 찾아 봅시다.

실행할 때 그냥 멈 춥니 다. 그것은 추락하지 않는 것 같습니다. 그냥 달려있다.

일부 디버거-FU를 사용하는 경우가 실제로에서 돌고있어, 다음 앱이 때 "매달려"것을 발견 할 것이다 (lldb-GDB 단지 OS X에서 마우스 오른쪽 버튼으로 작동하지 않습니다 사용하십시오) 이상한 루프가 귀하의 main 기능에 있으며, 아래 주석에 화살표로 표시되어 있습니다. 내가 루프의 중간에 위의 여분의 puts 전화를 추가

int 
main (void) 
{ 
    char st1[8192]; 
    char st2[8192]; 


    getcontext(&ctx[1]); 
    ctx[1].uc_stack.ss_sp = st1; 
    ctx[1].uc_stack.ss_size = sizeof st1; 
    ctx[1].uc_link = &ctx[0]; 
    makecontext(&ctx[1], f1, 0); 


    getcontext(&ctx[2]);// <---------------------+ back to here 
    ctx[2].uc_stack.ss_sp = st2;//    | 
    ctx[2].uc_stack.ss_size = sizeof st2;//  | 
    ctx[2].uc_link = &ctx[1];//     | 
    makecontext(&ctx[2], f2, 0); //    | 
    //           | 
    puts("about to swap...");//     | 
    //           | 
    swapcontext(&ctx[0], &ctx[2]);// ------------+ jumps from here 
    return 0; 
} 

참고. 그 행을 추가하고 다시 컴파일/실행하면, 그냥 매달려있는 프로그램 대신에 문자열 "about to swap..."을 분출하기 시작하는 것을 볼 수 있습니다.

주어진 스택 크기에 따라 분명히 뭔가가 진행되고 있으므로 ss_size이 참조되는 모든 곳을 살펴 보겠습니다 ...

(참고 :. 구현 ucontext 애플에 대한 신뢰할 수있는 소스 코드를 https://opensource.apple.com/source/에서이지만, 검색 및 연결하기위한 더 좋은이기 때문에 내가 사용하는 것 그 a GitHub mirror있다)

우리 take a look at makecontext.c, 우리는 무언가를보고하는 경우 좋아요 :

if (ucp->uc_stack.ss_size < MINSIGSTKSZ) { 
    // fail without an error code since makecontext is a void function 
    return; 
} 

음, 멋지 네요! MINSIGSTKSZ은 무엇입니까? 음, a look in signal.h 보자 :

#define MINSIGSTKSZ 32768 /* (32K)minimum allowable stack */ 
#define SIGSTKSZ 131072 /* (128K)recommended stack size */ 

은 분명히이 값은 실제로 part of the POSIX standard 있습니다. 이 값을 참조하는 ucontext 문서에는 아무 것도 보이지 않지만 ucontext preserves the current signal mask 이후로 암시 된 것 같습니다.

어쨌든, 이것은 우리가보고있는 비뚤어진 동작을 설명합니다. 호출이 너무 작기 때문에 스택 크기가 작기 때문에 getcontext(&ctx[2])을 호출하면 ctx[2]의 내용이 설정되므로 swapcontext(&ctx[0], &ctx[2])에 대한 호출이 다시 해당 라인으로 다시 스왑되어 무한 루프가 생성됩니다.

흥미롭게도 MINSIGSTKSZ은 os x에서 32768 바이트이지만 내 리눅스 박스에서는 2048 바이트 밖에 없으므로 Linux에서는 작동하지만 x에서는 작동하지 않는 이유를 설명합니다.

char st1[SIGSTKSZ]; 
char st2[SIGSTKSZ]; 

그, 또는 사용되지되지 않는 무언가로 전환 : 안전한 옵션 sys/signal.h에서 권장 스택 크기를 사용처럼이 모든 것을 바탕으로

, 그것은 보인다. C++을 싫어하는 사람이라면 Boost.Context을 살펴보십시오.

+0

멍청하다. 왜 그것을 고칠 수 있었습니까? 스택 크기를 늘리려면 어떻게 생각하니? – Prof

+1

@Prof - 나는 os x에 대한 ucontext를 사용하여 코드를 성공적으로 실행할 수 있다는 것을 알고 있었기 때문에 예제 코드가 내 리눅스 박스에서 작동했지만 os x에서는 작동하지 않았을 때 스택 크기가 가장 큰 원인으로 보였다. – DaoWen

+0

@Prof - 좀 더 파고 들었습니다. 왜 작은 스택 크기로 작동하지 않는지에 대한 자세한 내용으로 답변을 업데이트했습니다. 즐겨! – DaoWen