2011-02-01 18 views
2

誰かが私にこのコードスニペットを説明できますか? また、私はこれについてもっと知ることができるいくつかのリンク/ URLを教えてください? このコードは、私たちのライブラリ内の "extern int errno"を上書きするためのラッパーとして使用されます。誰かが私にこの機能を説明することができ、なぜいくつかのシステムコールでラッパーが必要だと言うことができますか? WeakSYSCALLSとも呼ばれる?syscallラッパー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

「システムコール」を実行すると、カーネルが特別なアクティビティを実行するようにトリガされます。カーネルは異なるアドレス空間で動作するので、単純な関数呼び出しではできません。

オペレーティングシステムとハードウェアプラットフォームによっては、割り込み、コールゲート、SYSENTER、または他のいくつかの方法をトリガするなどして、システムコールを呼び出すことができます。

いずれにしても、C関数呼び出しのやり方と同じように、いくつかのパラメータをカーネルに渡すことはできません。ただし、ですが、パラメータ値を特定のレジスタに配置してください。それらがどのレジスタであり、その内容がカーネルによってどのように解釈されるかは、問題のOSに固有です。あなたがアクセスでもない特定のレジスタは、またプレーンなCコードでは、前述のカーネル・トリガーのいずれかの方法を呼び出すことができるので

システムコールあるC言語の関数のようなと呼ばれるあなたに利用可能ラッパー、その後、場所がありますレジスタ内のパラメータはASMコードを使用してカーネルをトリガします。

上記の表示は、このようなシステムラッパーです。引数の数をレジスタ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'とのシンボルの衝突がないので、エラー見つからない。 –