malloc()とfree()原理と実装

malloc()と実装されたシステムを呼び出すことによって簡単に達成C言語でその派生関数を介してのみダイナミックアプリケーションメモリ(Linuxシステムコールではsbrkのを通して達成されます())。

malloc()最後に、我々はどこにメモリ空間を得ましたか。その答えは、原子炉内部からのスペースを取得することです。その関数は、ヒープのメモリへのポインタを返します。オペレーティングシステムは、レコードの空きメモリアドレスのリンクリストを持っています。オペレーティングシステムは、アプリケーションプログラムを受信すると、リンクリストをトラバースし、最初のスペースは、アプリケーション・ヒープ空間ノードよりも大きい見つけ、次いで遊離のノードからノードを削除しますリストをリンクし、接合スペースの点は、プログラムに割り当てられました。

メモリを割り当てるためにmalloc()が実行時に動的に割り当てられ、その割り当てられたメモリを解放する()自由。着信ユーザの大きさは、また、追加のメモリ管理に関連するが、ユーザが見ることができない割り当てられた場合のmalloc()が割り当てられました。そのため、

管理スペースの実際のサイズ=スペース+ユーザー

64ビット・システムでは、malloc関数のビット24(0)有効なメモリサイズ、32、12は、少なくとも非常に多くのことを言うために正確であり、これらはメモリに使用することができます

結果

また、ヒープメモリブロックは常にブロックに割り当てられ、どのように多くのバイトは適用されていない、メモリのバイト数が出て提供するために使用します。ヒープメモリのブロックサイズは、一般に、関連するメモリ(8バイト(32ビットシステムの場合)または64ビットシステム用の16バイト()と整列しています。

したがって、システム64、(アプリケーションメモリサイズ+はsizeof(構造体mem_control_block))だけ全容量の割り当てを完了するために、%16 == 0、しかしときに!= 0、メモリ割り当てになりますよりブロック。

ヒープメモリブロックにプログラムがメモリ・ブロックによって管理されている次のLinuxスタック管理システム、異なるサイズの、すなわちたくさん。どのようなクエリのブロックサイズは、ブロックがプログラムによって使用されているかどうかをクエリは、どのようにこのブロックのアドレスを知っていますかどのようにこれらのブロック管理ネパール、。次のようにメモリブロック管理のメモリ設計データ構造へのブロックの管理を解決するために、詳細なデータ構造です。

/**内存控制块数据结构,用于管理所有的内存块
* is_available: 标志着该块是否可用。1表示可用,0表示不可用
* size: 该块的大小
**/
struct mem_control_block {
    int is_available;
    int size;
};

 

 

その後、メモリヒープイエにおける組織であることを、理解メモリブロックの管理データ構造と、スタックがメモリの多くのブロックから構成され、それは以下の図を有します。

メモリヒープのプロセスを増加した後、

上記の知識を統合し、簡単に)(mallocの実装の一般的なアイデアを考えることができます。ヒープメモリをチェックするために一つ一つ目は利用可能であり、それが満たすことができるかどうかもしそうならサイズ要件は、直接使用上の単語場合は満たされています。すべてのメモリ・ブロックを横断するとき、唯一のオペレーティングシステムへのシステムコール、新しいメモリのアプリケーションを介してブロックのニーズを満たし、その後、ヒープに新しいメモリを追加することができない場合は一方で、ヒープ。アイデアは、フローチャートを実現するためのmalloc()、非常に単純で、次のとおりです。

フローチャートを実現するためのmalloc()

上記のアイデアを読んだ後、それは限り、メモリ管理ブロックは、それに利用可能になるよう、アイデアの実現の自由()関数を考えることは非常に簡単になります。その結果、メモリブロックを再割り当てブロックとして割り当てることができるのmalloc()関数の次の呼び出し。

最後に、malloc関数()とfree()の実装コードを貼り付けます。

malloc()の実装:

/**内存控制块数据结构,用于管理所有的内存块
* is_available: 标志着该块是否可用。1表示可用,0表示不可用
* size: 该块的大小
**/
struct mem_control_block {
    int is_available;
    int size;
};

/**在实现malloc时要用到linux下的全局变量
*managed_memory_start:该指针指向进程的堆底,也就是堆中的第一个内存块
*last_valid_address:该指针指向进程的堆顶,也就是堆中最后一个内存块的末地址
**/
void *managed_memory_start;
void *last_valid_address;

/**malloc()功能是动态的分配一块满足参数要求的内存块
*numbytes:该参数表明要申请多大的内存空间
*返回值:函数执行结束后将返回满足参数要求的内存块首地址,要是没有分配成功则返回NULL
**/
void *malloc(size_t numbytes) {
    //游标,指向当前的内存块
    void *current_location;
    //保存当前内存块的内存控制结构
    struct mem_control_block *current_location_mcb;
    //保存满足条件的内存块的地址用于函数返回
    void *memory_location;
    memory_location = NULL;
    //计算内存块的实际大小,也就是函数参数指定的大小+内存控制块的大小
    numbytes = numbytes + sizeof(struct mem_control_block);
    //利用全局变量得到堆中的第一个内存块的地址
    current_location = managed_memory_start;

    //对堆中的内存块进行遍历,找合适的内存块
    while (current_location != last_valid_address) //检查是否遍历到堆顶了
    {
        //取得当前内存块的内存控制结构
        current_location_mcb = (struct mem_control_block*)current_location;
        //判断该块是否可用
        if (current_location_mcb->is_available)
            //检查该块大小是否满足
            if (current_location_mcb->size >= numbytes)
            {
                //满足的块将其标志为不可用
                current_location_mcb->is_available = 0;
                //得到该块的地址,结束遍历
                memory_location = current_location;
                break;
            }
        //取得下一个内存块
        current_location = current_location + current_location_mcb->size;
    }

    //在堆中已有的内存块中没有找到满足条件的内存块时执行下面的函数
    if (!memory_location)
    {
        //向操作系统申请新的内存块
        if (sbrk(numbytes) == -1)
            return NULL;//申请失败,说明系统没有可用内存
        memory_location = last_valid_address;
        last_valid_address = last_valid_address + numbytes;
        current_location_mcb = (struct mem_control_block)memory_location;
        current_location_mcb->is_available = 0;
        current_location_mcb->size = numbytes;
    }
    //到此已经得到所要的内存块,现在要做的是越过内存控制块返回内存块的首地址
    memory_location = memory_location + sizeof(struct mem_control_block);
    return memory_location;
}

 

無料()の実装:

/**free()功能是将参数指向的内存块进行释放
*firstbyte:要释放的内存块首地址
*返回值:空
**/
void free(void *firstbyte)
{
    struct mem_control_block *mcb;
    //取得该块的内存控制块的首地址
    mcb = firstbyte - sizeof(struct mem_control_block);
    //将该块标志设为可用
    mcb->is_available = 1;
    return;
}

 

 

 参考:

      https://blog.csdn.net/c1s2p3/article/details/50522185

      https://blog.csdn.net/qq_29350001/article/details/70213602

      https://www.cnblogs.com/debuging/p/3158147.html

公開された407元の記事 ウォンの賞賛150 ビュー380 000 +

おすすめ

転載: blog.csdn.net/ds1130071727/article/details/102551928