1

最近、私は JOS カーネル (私のような初心者を支援するために主に学習目的で MIT で開発されたもの) のコードを調べていて、小さな疑問を思いつきました。 .

これは、 「.c」ファイルからの小さなコードです:-

if(n>0)
           {
            nextfree = ROUNDUP((char *) nextfree, PGSIZE);
            result=nextfree;
            nextfree+=n;
            PADDR(nextfree);
           }

対応する「.h」ファイル:-

/* This macro takes a kernel virtual address -- an address that points above
* KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
* and returns the corresponding physical address.  It panics if you pass it a
* non-kernel virtual address.
*/

    #define PADDR(kva)                      \
    ({                              \
    physaddr_t __m_kva = (physaddr_t) (kva);        \
    if (__m_kva < KERNBASE)                 \
    panic("PADDR called with invalid kva %08lx", __m_kva);\
    __m_kva - KERNBASE;                 \
    })

上記の構造に関して 2 つの質問があります。

  1. PADDR(nextfree)上記のように変数をvar=PADDR(nextfree)直接呼び出すのではなく、変数に値を割り当てるべきではありませんか。それはどのようにうまくいくでしょうか?

  2. 把握しやすい指定されたタスクの関数を作成するよりも、ヘッダー ファイルにそのような小さくて複雑な定義を記述することを好む人がいるでしょうか。

4

2 に答える 2

1

さて...これをアンピックします:

  1. 括弧に注意してください。これは、その中にあるものは何でも単一の値に減少することを意味します...
  2. 中括弧に注意してください。ここで新しいブロック スコープを定義しています。
  3. 新しいスコープに入ったので、好きな変数を安全に定義できます。変数はこのブロックをエスケープしないからです。
  4. 最後のステートメントは式で構成されます。
  5. したがって、スコープの値は、最後のステートメントのその式の値です。
  6. したがって、マクロの戻り値は です__m_kva - KERNBASE

したがって、質問1に答えるには、値を返しますが、例のスニペットでは、この返された値は単に使用されていません。ただし、おそらくマクロを呼び出す他のコードはその値を使用します。質問 2 に答えるには: それは状況によります。関数ではできないことを、マクロで行うことができundefiningます。この場合、プログラマーは一般的なエラー チェックを複製する必要があり、サンプル スニペットでそれを行うために変換マクロを使用したようです。free(次の解放が誤ってユーザー空間メモリなどを試みないことを事前に確認します。)

于 2013-10-15T23:43:22.343 に答える