XINUシステムコールの理解 - getstk.c [閉じる]

XINUシステムコールの理解 - getstk.c [閉じる]

このシステムコールが終了すると、何が起こり、なぜ起こるのかを概念的に理解することはできません。 getstk.cメソッドが利用可能なスペースの中で最も高いメモリアドレスを返すことは理解していますが、いくつかのコードが何をしているのかわかりません。これが明確になればいいでしょう。完全に理解できないコード領域はアスタリスクで強調表示されます。

/* getstk.c - getstk */

#include <xinu.h>

/*------------------------------------------------------------------------
 *  getstk  -  Allocate stack memory, returning highest word address
 *------------------------------------------------------------------------
 */
char    *getstk(
          uint32        nbytes          /* size of memory requested     */
        )
{
        intmask mask;                   /* saved interrupt mask         */
        struct  memblk  *prev, *curr;   /* walk through memory list     */
        struct  memblk  *fits, *fitsprev; /* record block that fits     */

        mask = disable();
        if (nbytes == 0) {
                restore(mask);
                return (char *)SYSERR;
        }

        nbytes = (uint32) roundmb(nbytes);      /* use mblock multiples */

        prev = &memlist;
        curr = memlist.mnext;
        fits = NULL;
        fitsprev = NULL;  /* to avoid a compiler warning */

        while (curr != NULL) {                  /* scan entire list     */
                if (curr->mlength >= nbytes) {  /* record block address */
                        fits = curr;            /*   when request fits  */
                        fitsprev = prev;
                }
                prev = curr;
                curr = curr->mnext;
        }

        if (fits == NULL) {                     /* no block was found   */
                restore(mask);
                return (char *)SYSERR;
        }
        if (nbytes == fits->mlength) {          /* block is exact match */
                fitsprev->mnext = fits->mnext;
        **} else {                                /* remove top section   */
                fits->mlength -= nbytes;
                fits = (struct memblk *)((uint32)fits + fits->mlength);
        }**
        memlist.mlength -= nbytes;
        restore(mask);
        **return (char *)((uint32) fits + nbytes - sizeof(uint32));**
}

struct memblk はここにあります:

struct  memblk  {           /* see roundmb & truncmb    */
    struct  memblk  *mnext;     /* ptr to next free memory blk  */
    uint32  mlength;        /* size of blk (includes memblk)*/
    };
extern  struct  memblk  memlist;    /* head of free memory list */

なぜfit + nbytes - sizeof(uint32)を返すのですか? fit(構造体)をuint32型に変換したのはなぜですか?

ベストアンサー1

これは、十分なサイズのブロックが見つかる2つのケースです。最初のケースでは、fits前のノードの次のポインタをこのノードの次のポインタに接続して、ノード全体()を削除します。memlistその後、このブロックは戻り値に使用されるため、ブロックやコメントなどを通じて、ここの目的はプールから空きメモリを見つけて使用するために空きプールから削除することだと推測します。

    if (nbytes == fits->mlength) {          /* block is exact match */
            fitsprev->mnext = fits->mnext;
    **} else {                                /* remove top section   */
            fits->mlength -= nbytes;
            fits = (struct memblk *)((uint32)fits + fits->mlength);
    }**

今強調した2番目のケースで見つかったブロックは次のとおりです。十分に大きい。超過した内容は無駄になるため、内容全体を返さないことが重要です。また、戻り値の特性(以下を参照)は、受信者がレコードの実際のサイズを持っていないことを意味するため、次のようにブロックがリサイクルされると後で検索されます。必要なサイズ(パラメータの元の値nbytes)、メモリプールから無駄な過剰分を永久に分離します。

この問題を解決するためにfitsブロックを短縮しました。残りの長さだけ。それは、要求ブロックの長さではありませんただし、見つかった(十分に大きい)ブロックの長さから要求された量を引いたときの残りの量。 if/elseの最初の節とは異なり、ここのFitsブロックは次のようになります。削除されないプールで。単に短縮:

 fits->mlength -= nbytes;

戻り値に使用されたポインタは、新しく短縮されたブロックの終わりに移動されます。これはプールから削除される領域を指します。

 fits = (struct memblk *)((uint32)fits + fits->mlength);

fitsポインタが移動しても、コードは現在指している領域(前の行の位置とは異なります)fits->mlengthのサイズを変更しません。fitsコンテンツが返されたためです。構造ではない。この関数はstruct memblkまったく使用されていない場所で呼び出されるようです。つまり、struct memblkこのコードで使用されるのは次のとおりです。しかし、発信者ではありません。したがって、パブリックAPIの一部ではgetstk()ないパブリックAPI呼び出しを考えることができます。struct memblkこれは内部メカニズムの一部にすぎません。

戻り値は、メモリ領域の一番上(最も高い点)を指すcharポインタだけです。

getstk  -  Allocate stack memory, returning highest word address

おそらく呼び出し側は、返されたポインタが次を指すと仮定します。トップ領域のサイズですnbytes。これは malloc() が行うことと非常によく似ています。たとえば、次のようになります。

char *dataA = malloc(4096);
char *dataB = getstk(4096);

mallocがアドレスを返すことを除いて床に4096バイトブロックなので、アドレス範囲はdataA〜ですdataA + 4095。 getstk()は高いアドレスを返すので、範囲は〜dataB - 4095dataB実際には「単語サイズ」が使用されるので正確ではありません。読み続けてください)です。

したがって:

    return (char *)((uint32) fits + nbytes - sizeof(uint32));

これは現在下向きの領域です(nbytes通常私たちが考えるfits初期アドレス、mallocと同じ)。ただし、getstk()は高いアドレスを返す必要があります。より正確にはトップレベルの単語アドレス。 「単語」は通常4バイト/ 32ビットですsizeof(uint32)。したがって、返されたアドレスはnbytesブロックサイズの最後の4バイトを指します(実際にはnbytesはroundmb()で丸められますが、おそらくこのシステムはリサイクルにも使用されます)。

おすすめ記事