4

私には割り当てがあり、できる限り最善を尽くしましたが、何を試しても最適なスキームを得ることができません。以下はコードです。slob_page_allocベスト フィットを実装するために、関数に変更を加えました。コードを以下に示します。

static void *slob_page_alloc(struct page *sp, size_t size, int align)
{
    slob_t *prev, *cur, *aligned = NULL, *best_fit=NULL;
    /* See SLOB_UNITS defination for meaning of macro. units is required 
     * number OF units.*/
    int delta = 0, units = SLOB_UNITS(size);
    unsigned long frag_size = -1UL;
    /*Iterate throught the whole page to find best fit*/
    //printk("Before the for loop\n");
    printk("Starting slob_page_alloc execution\t"); 
    for(prev=NULL, cur=sp->freelist; ; prev=cur, cur=slob_next(cur)) {
        slobidx_t avail = slob_units(cur);
        if(align) {
            aligned = (slob_t *)ALIGN((unsigned long)cur, align);
            delta = aligned - cur;
        }
        if(avail >= delta+units) {
            if( frag_size > avail-units ) {
                frag_size = avail-units;
                best_fit = cur;
            }
        }
        if(slob_last(cur))
            break;
    }

    //printk("after the for loop.\n");
    if(best_fit) {
        slobidx_t avail = slob_units(best_fit);
        //printk("best fit found\n");

        if (align) {
            aligned = (slob_t *)ALIGN((unsigned long)best_fit, align);
            delta = aligned - best_fit;
        }
        if (avail >= units + delta) { /* room enough? */
            slob_t *next;

            if (delta) { /* need to fragment head to align? */
                next = slob_next(best_fit);
                /*Update the newly fragmented slob*/
                set_slob(aligned, avail - delta, next);
                /* Update the lod slob about reduced size 
                 * and new next slob*/
                set_slob(best_fit, delta, aligned);
                prev = best_fit;
                best_fit = aligned;
                avail = slob_units(best_fit);
            }

            next = slob_next(best_fit);
            if (avail == units) { /* exact fit? unlink. */
                if (prev)
                    set_slob(prev, slob_units(prev), next);
                else
                    sp->freelist = next;
            } else { /* fragment */
                if (prev)
                    set_slob(prev, slob_units(prev), best_fit + units);
                else
                    sp->freelist = best_fit + units;
                set_slob(best_fit + units, avail - units, next);
            }

            sp->units -= units;
            if (!sp->units)
                clear_slob_page_free(sp);
            printk("Returned from slob_page_alloc\t");
            return best_fit;
        }
    }
    printk("Returned from slob_page_alloc\t");
    return NULL;
}

このスキームでカーネルを構成すると、どこかでハングします。

デバッグ:

この機能と機能のどこかで印刷を行いましたslob_alloc。私には意味がありませんが、私の関数は何度も呼び出されて正常に戻り、再び呼び出されて戻ります。しかし、ある時点で呼び出されると、この関数内のステートメントが出力されますが、呼び出し先からのステートメントは出力されず、無期限にハングします。

どんな助けでも大歓迎です!! ありがとう。

4

2 に答える 2

4

ここには何が問題なのかを理解するのに十分なコードがないと思います (おそらく lxr.oss.org.cn/source/mm/slob.c にあるかもしれませんが、私は確認しませんでした)。しかし、ここに私が推測しているのはあなたの問題です:

どういうわけか、リンクされたリストでループ (または「サイクル」) が発生しているため、slob_last(cur) への呼び出しは決して true を返しません。(あなたのコードはその行に到達します。セグメンテーション違反以外には、それを妨げるものは何もありません。)リストをスキャンして終了またはループがあるかどうかを確認し、出力するデバッグ関数を追加しました。ループがある場合のメッセージ。次に、関数にその関数への呼び出しを追加しました。Bob Floyd のペットの亀とウサギについて聞いたことがない場合は、Google for Bob Floyd とリンク リスト ループ検出 (またはリンク リスト サイクル検出) を参照してください。以下のコードはテストしていませんが、正しくコーディングしたと思います。ループが検出された場合は、slob_t をリストに追加するロジックを調べ、それらをリストから削除するコードを調べます。そこには' リストに何かを不適切に追加したり、リストから何かを不適切に削除したりする何らかの条件が必要です。ここでループが見つかった場合は、他の場所への呼び出しを追加してください...リストを変更するコード内のすべてのポイントの直前と直後...そうすれば、コードのどの部分がループを引き起こしているかを絞り込むことができます.

static void slob_debug_detect_loop(slob_t *list_head, const char* debug_location)
{
    // Bob Floyd's pet tortoise & hare, both born in 1967...
    slot_t *hare = list_head;
    slob_t *tortoise = list_head;
    int tortoise_pacer=0;
    while (!slob_last(hare))
    {
        hare = slob_next(hare);
        if (++tortoise_pacer&1)
            tortoise = slob_next(tortoise);
        if (tortoise_pacer>2 && hare==tortoise)
        {
            printk("LINKED LIST LOOP DETECTED at %s!\n", debug_location);
            return;
        }
    }
}



static void *slob_page_alloc(struct page *sp, size_t size, int align)
{
    slob_t *prev, *cur, *aligned = NULL, *best_fit=NULL;
    /* See SLOB_UNITS defination for meaning of macro. units is required
    * number OF units.*/
    int delta = 0, units = SLOB_UNITS(size);
    unsigned long frag_size = -1UL;
    /*Iterate throught the whole page to find best fit*/
    //printk("Before the for loop\n");
    printk("Starting slob_page_alloc execution\t");
    slob_debug_detect_loop(sp->freelist, "before best-fit detection loop"); // ++++++++++
    for(prev=NULL, cur=sp->freelist; ; prev=cur, cur=slob_next(cur)) {
        slobidx_t avail = slob_units(cur);
        if(align) {
            aligned = (slob_t *)ALIGN((unsigned long)cur, align);
            delta = aligned - cur;
        }
        if(avail >= delta+units) {
            if( frag_size > avail-units ) {
                frag_size = avail-units;
                best_fit = cur;
            }
        }
        if(slob_last(cur))
            break;
    }
.
.
.
于 2012-12-08T08:10:26.090 に答える
2

問題は、best_fitを見つけたときに壊れないが、slob_last(cur)で壊れるので、prevポインターが間違っていることです。best_fitポインタは最後のbest_fitですが、prevはlastのprevです。

コードリストの後半で、prevがbest_fitのprevエントリであるという前提でsが変更されます。リストがめちゃくちゃになると、無限ループになります。

于 2012-12-12T16:40:24.177 に答える