質問: malloc()は内部的にどのように実装されていますか? malloc()が内部的にどのように機能するかを説明できますか?私は時々strace programを実行しましたが、sbrkシステムコールをたくさん見て、man sbrkがmalloc()で使用されていることについて話しますが、それ以上ではありません。
回答: sbrksystem呼び出しは、データセグメントの「境界線」を移動します。これは、プログラムがデータを読み書きできる領域の境界線を移動することを意味します(ただし、mallocが実際にメモリセグメントをそのメソッドでカーネルに戻すことはありませんが、拡大または縮小させます)。それとは別に、ファイルをメモリにマップするために使用されるmmapもありますが、メモリの割り当てにも使用されます(共有メモリを割り当てる必要がある場合は、mmapがその方法です)。そのため、カーネルからより多くのメモリを取得する2つの方法があります:sbrkおよびmmap。カーネルから取得したメモリを整理する方法については、さまざまな戦略があります。単純な方法の1つは、特定の構造サイズ専用の「バケット」と呼ばれるゾーンにパーティションを分割することです。たとえば、malloc実装は、16、64、256、および1024バイト構造のバケットを作成できます。 mallocに指定サイズのメモリを提供するように要求すると、その数が次のバケットサイズに切り上げられ、そのバケットから要素が提供されます。より広い領域が必要な場合は、mallocはmmapを使用してカーネルに直接割り当てることができます。特定のサイズのバケットが空の場合、mallocはsbrkを使用して、新しいバケット用のスペースをさらに取得できます。さまざまなmallocデザインがあり、速度、オーバーヘッド、およびフラグメンテーション/スペースの有効性を回避することを妥協する必要があるため、mallocを実装する正しい方法はありません。たとえば、バケットが要素を使い果たした場合、実装はより大きなバケットから要素を取得し、それを分割して、要素を使い果たしたバケットに追加します。これはスペース効率が非常に高くなりますが、すべてのデザインで可能になるわけではありません。 sbrk/mmapを介して別のバケットを取得するだけの場合は、より高速で簡単ですが、スペース効率は良くありません。また、設計ではもちろん、「フリー」でmallocが再び何らかの方法でスペースを使用できるようにする必要があることを考慮する必要があります。再利用せずにメモリを渡すだけではありません。興味があるなら、openser/kamailio sipプロキシには2つのmalloc実装があります(共有メモリを多用し、システムmallocは共有メモリをサポートしないため、独自に実装する必要があります)。参照: https://github.com/opensips/opensips/tree/master/mem 次に、 gnu libc malloc implementation を見ることができますが、これは非常に複雑です、iirc。