2011-02-01 1 views
2

누군가이 코드 스 니펫을 설명 할 수 있습니까? 또한이 링크에 대해 더 자세히 알 수있는 링크/URL을 알려주십시오. 이 코드는 라이브러리의 "extern int errno"를 재정의하는 래퍼로 사용됩니다. 누군가이 함수를 설명 할 수 있고 왜 일부 시스템 콜에 래퍼가 필요하다고 말할 수 있습니까? WeakSYSCALLS라고도하는 것은 무엇입니까?syscall wrapper asm C

#define ASM_ARGS_1  ASM_ARGS_0, "r" (_a1) 
#define ASM_ARGS_2  ASM_ARGS_1, "r" (_a2) 
#define ASM_ARGS_3  ASM_ARGS_2, "r" (_a3) 
#define LOADREGS_5(a1, a2, a3, a4, a5)   \ 
register int _v1 asm ("v1") = (int) (a5);  \ 
LOADREGS_4 (a1, a2, a3, a4) 

#define LOADREGS_6(a1, a2, a3, a4, a5, a6)  \ 

register int _v2 asm ("v2") = (int) (a6);  \ 

LOADREGS_5 (a1, a2, a3, a4, a5) 

#define MYLIBC_SYSCALL(name, nargs, args...)    \ 
({              \ 

    unsigned int retval;        \ 

    {             \ 

    register int _a1 asm ("r0"), _nargs asm ("r7"); \ 
    LOADREGS_##nargs(args)       \ 
    _nargs = __NR_##name;        \ 
    asm volatile (         \ 
      "swi 0x0"        \ 
      :"=r"(_a1)        \ 
      :"r"(_nargs) ASM_ARGS_##nargs    \ 
      : "memory");        \ 

     retval = _a1;          \ 
    }             \ 

    if (retval >= 0xfffff001)  {     \ 
      errno = -retval;       \ 
      retval = (unsigned int)-1;      \ 
    }             \ 
    (int) retval;          \ 
}) 
+0

대답은 무엇입니까? – kingsmasher1

답변

5

"시스템 호출"을 수행하는 것은 커널이 특수 활동을 실행하도록 트리거하는 것을 의미합니다. 커널이 다른 주소 공간에서 실행되기 때문에 간단한 함수 호출을 통해 커널을 수행 할 수 없습니다.

운영 체제 및 하드웨어 플랫폼에 따라 syscall은 예를 들어 인터럽트, 콜 게이트, SYSENTER 또는 다른 여러 가지 메소드를 트리거하여 호출 할 수 있습니다.

그러나 C 함수 호출로 수행하는 것처럼 커널에 여러 매개 변수를 전달할 수는 없습니다. 그러나 일 수 있지만 매개 변수 값을 특정 레지스터에 배치하십시오. 그러한 레지스터들과 그 내용들이 커널에 의해 어떻게 해석되는지는 문제의 OS에만 적용됩니다. 액세스도 특정 레지스터는 없으며, 일반 C 코드에서, 위에서 언급 한 커널 트리거 방법 중 하나를 호출 할 수 있기 때문에

, 콜의 있는 C 함수와 같은라고 당신에게 가능 래퍼, 그리고 장소가있다 레지스터의 매개 변수는 ASM 코드를 사용하여 커널을 트리거합니다.

위의 내용은 syscall 래퍼입니다. 인수의 수를 레지스터 r7에 넣는 부분과 인수 자체를 해당 레지스터 (LOADREGS_*)에 넣은 다음 트리거를 수행합니다 (swi 0x0, 어느 것인가 이라고 생각하면은 소프트웨어 인터럽트입니다. ARM 플랫폼)를 호출하고 A1 레지스터에서 "반환 값"을 가져옵니다.

+0

맞음, SWI는 소프트웨어 인터럽트입니다. –

0

시스템 호출은 errno을 직접 설정할 수 없으며 음수 값을 반환합니다. errno은 실제로 왼쪽 값으로 평가되는 매크로라고 가정합니다.

이 코드는 C 라이브러리가 아닌 errno를 업데이트합니다.

+0

코드에 errno에 대한 선언이 없으므로 실제로 업데이트되는 errno에 대해 확신하지 못할 수 있습니다. 이것은 커널 내부의 시스템 호출 구현이 아니라 C 라이브러리의 일종의 래퍼입니다. – BjoernD

+0

요점은'extern int errno;'는 거의 항상 틀린 데, 왜냐하면 사양은'errno'를 매크로로 요구하기 때문입니다. 이미 다른 정의를 어딘가에 가지고 있다면 더 잘못된 것입니다. GNU C 라이브러리는'(* (__ errno_location()))'또는 유사한 표현식을 사용하여'errno'의 * thread-local * 구현을 찾습니다. 그래서 다른'errno'와의 심볼 충돌이 없으므로 오류가 발생합니다 간다. –