Minimum çalıştırılabilir örnek
Brk () sistem çağrısı ne yapar?
Çekirdekten, yığın adı verilen bitişik bir bellek yığınını okumanıza ve yazmanıza izin vermesini ister.
Eğer sormazsanız, sizi parçalayabilir.
Olmadan brk:
#define _GNU_SOURCE
#include <unistd.h>
int main(void) {
/* Get the first address beyond the end of the heap. */
void *b = sbrk(0);
int *p = (int *)b;
/* May segfault because it is outside of the heap. */
*p = 1;
return 0;
}
İle brk:
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b = sbrk(0);
int *p = (int *)b;
/* Move it 2 ints forward */
brk(p + 2);
/* Use the ints. */
*p = 1;
*(p + 1) = 2;
assert(*p == 1);
assert(*(p + 1) == 2);
/* Deallocate back. */
brk(b);
return 0;
}
GitHub akış yukarı .
Yukarıdakiler, yeni bir sayfaya brkçarpmayabilir ve olmadan bile segfault yapamaz , bu nedenle 16MiB'yi ayıran ve agresif olmayan brk:
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b;
char *p, *end;
b = sbrk(0);
p = (char *)b;
end = p + 0x1000000;
brk(end);
while (p < end) {
*(p++) = 1;
}
brk(b);
return 0;
}
Ubuntu 18.04'te test edildi.
Sanal adres alanı görselleştirme
Önce brk:
+------+ <-- Heap Start == Heap End
Sonra brk(p + 2):
+------+ <-- Heap Start + 2 * sizof(int) == Heap End
| |
| You can now write your ints
| in this memory area.
| |
+------+ <-- Heap Start
Sonra brk(b):
+------+ <-- Heap Start == Heap End
Adres alanlarını daha iyi anlamak için, disk belleği hakkında bilgi sahibi olmalısınız: x86 disk belleği nasıl çalışır? .
Neden ikisine de ihtiyacımız var brkve sbrk?
brkElbette sbrk+ ofset hesaplamaları ile uygulanabilir , her ikisi de sadece kolaylık sağlamak için mevcuttur.
Arka uçta, Linux çekirdeği v5.0, brkher ikisini de uygulamak için kullanılan tek bir sistem çağrısına sahiptir: https://github.com/torvalds/linux/blob/v5.0/arch/x86/entry/syscalls/syscall_64. tbl # L23
12 common brk __x64_sys_brk
Mı brkPOSIX?
brkeskiden POSIX idi, ancak POSIX 2001'de kaldırıldı, bu nedenle _GNU_SOURCEglibc sarmalayıcısına erişme ihtiyacı .
Kaldırma işlemi büyük olasılıkla mmap, birden fazla aralığın atanmasına izin veren bir üst küme ve daha fazla ayırma seçeneğinden kaynaklanmaktadır.
Bugün brkyerine mallocya da yerine kullanmanız gereken geçerli bir durum olmadığını düşünüyorum mmap.
brk vs malloc
brkeski bir uygulama olasılığıdır malloc.
mmapşu anda tüm POSIX sistemlerinin uygulamak için kullandığı daha yeni ve daha güçlü bir mekanizmadır malloc. İşte asgari çalıştırılabilir mmapbellek ayırma örneği .
Karıştırıp brkyanlış yerleştirebilir miyim ?
Eğer mallocuygulandıysa brk, bunun nasıl bir şeyleri havaya uçuramayacağı hakkında hiçbir fikrim yok, çünkü brksadece tek bir bellek aralığını yönetiyor.
Ancak glibc belgelerinde bu konuda bir şey bulamadım, örneğin:
Muhtemelen orada mmapkullanıldığından beri işler muhtemelen orada çalışacaktır malloc.
Ayrıca bakınız:
Daha fazla bilgi
Dahili olarak, işlemin bu kadar fazla belleğe sahip olup olamayacağına karar verir ve bu kullanım için bellek sayfalarını belirler .
Bu, yığının yığınla nasıl karşılaştırıldığını açıklar: x86 derlemesindeki kayıtlarda kullanılan push / pop yönergelerinin işlevi nedir?