linux中的内存管理:实现第一个适合

时间:2012-12-05 16:57:12

标签: c linux linux-kernel kernel

我已经完成任务,但我已尽力而为,但无论我尝试什么,我都无法获得最合适的方案。以下是代码。为了实现最佳匹配,我对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功能中进行了打印。虽然它对我没有任何意义,但我的函数被多次调用并成功返回,然后再次被调用并返回等等。但是有一次它被调用打印出这个函数中的语句,但是不会打印来自被调用者的语句而只是无限期地挂起它。

任何帮助表示赞赏!! 感谢。

2 个答案:

答案 0 :(得分:4)

我认为这里没有足够的代码来弄清楚什么是错的(也许在lxr.oss.org.cn/source/mm/slob.c,但我没有检查)。但这就是我猜你的问题:

不知何故,你在链表中得到一个循环(或'循环'),所以你对slob_last(cur)的调用永远不会返回true。 (你的代码确实到达了那一行;没有任何事情,没有一个段错误,这将阻止它。)我添加了一个调试函数,它将扫描列表以查看它是否终止或有一个循环,并打印出来如果有循环的消息。然后我在你的函数中添加了对该函数的调用。如果你还没有听说过鲍勃弗洛伊德的宠物乌龟和野兔之前,谷歌为鲍勃弗洛伊德和链表循环检测(或链表循环检测)。我没有在下面测试我的代码,但我认为我编码正确。如果它检测到循环,那么查看将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;
    }
.
.
.

答案 1 :(得分:2)

问题是prev指针是错误的,因为你没有 当你找到best_fit但打破了slob_last(cur)时休息。 best_fit指针是最后一个best_fit,但prev是最后一个。

稍后在代码列表中修改了假设prev 是best_fit的热门词条。当列表搞乱时,你会得到一个无限循环。