ตัวอย่างที่เรียกใช้น้อยที่สุด
การเรียกระบบ brk () ทำอะไรได้บ้าง?
ขอเคอร์เนลให้คุณอ่านและเขียนหน่วยความจำต่อเนื่องที่เรียกว่าฮีป
ถ้าคุณไม่ถามมันอาจเป็นการแยกคุณออก
โดยไม่ต้อง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;
}
ด้วย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 ต้นน้ำ
ด้านบนอาจไม่ตีหน้าใหม่และไม่แยก segfault แม้จะไม่มีbrk
ดังนั้นนี่เป็นเวอร์ชั่นที่ก้าวร้าวมากขึ้นซึ่งจัดสรร 16MiB และมีแนวโน้มที่จะ segfault โดยไม่ต้อง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
การสร้างภาพพื้นที่ที่อยู่เสมือน
ก่อนbrk
:
+------+ <-- Heap Start == Heap End
หลังbrk(p + 2)
:
+------+ <-- Heap Start + 2 * sizof(int) == Heap End
| |
| You can now write your ints
| in this memory area.
| |
+------+ <-- Heap Start
หลังbrk(b)
:
+------+ <-- Heap Start == Heap End
เพื่อให้เข้าใจถึงช่องว่างที่อยู่ได้ดีขึ้นคุณควรทำความคุ้นเคยกับการเพจ: การเพจจิ้ง x86 ทำงานอย่างไร? .
ทำไมเราต้องการทั้งสองอย่างbrk
และsbrk
?
brk
สามารถนำไปใช้กับการsbrk
คำนวณ + ออฟเซ็ตซึ่งทั้งสองมีอยู่เพื่อความสะดวก
ในส่วนแบ็คเอนด์เคอร์เนล Linux v5.0 มีการเรียกระบบเดียวbrk
ที่ใช้ในการดำเนินการทั้งสองอย่าง: https://github.com/torvalds/linux/blob/v5.0/arch/x86/entry/syscalls/syscall_64 tbl # L23
12 common brk __x64_sys_brk
brk
POSIX คืออะไร
brk
เคยเป็น POSIX แต่มันถูกลบใน POSIX 2001 ดังนั้นจึงจำเป็นต้อง_GNU_SOURCE
เข้าถึง glibc wrapper
การลบนี้น่าจะเกิดจากการแนะนำmmap
ซึ่งเป็น superset ที่อนุญาตให้มีการจัดสรรหลายช่วงและตัวเลือกการจัดสรรเพิ่มเติม
ฉันคิดว่าไม่มีกรณีที่ถูกต้องที่คุณควรใช้brk
แทนmalloc
หรือmmap
ทุกวันนี้
brk
VS malloc
brk
malloc
เป็นหนึ่งในความเป็นไปได้ของการใช้เก่า
mmap
เป็นรุ่นใหม่ที่มีประสิทธิภาพมากขึ้น stricly กลไกซึ่งมีแนวโน้มที่ทุกระบบ POSIX malloc
ใช้อยู่ในปัจจุบันในการดำเนินการ นี่คือที่ทำงานได้น้อยที่สุดmmap
เช่นการจัดสรรหน่วยความจำ
ฉันสามารถผสมbrk
และ malloc ได้หรือไม่?
หากคุณmalloc
นำไปใช้กับbrk
ฉันไม่ทราบว่าวิธีการที่ไม่สามารถระเบิดสิ่งต่าง ๆ เนื่องจากbrk
จัดการหน่วยความจำช่วงเดียวเท่านั้น
อย่างไรก็ตามฉันไม่พบอะไรเกี่ยวกับเรื่องนี้ในเอกสาร glibc เช่น:
สิ่งที่อาจจะเป็นเพียงแค่ทำงานที่นั่นผมคิดว่าตั้งแต่มีแนวโน้มที่จะใช้สำหรับการmmap
malloc
ดูสิ่งนี้ด้วย:
ข้อมูลเพิ่มเติม
ภายในเคอร์เนลจะตัดสินว่ากระบวนการสามารถมีหน่วยความจำขนาดนั้นหรือไม่และหน้าหน่วยความจำ earmarks สำหรับการใช้งานนั้น
สิ่งนี้อธิบายถึงการเปรียบเทียบสแต็กกับฮีป: ฟังก์ชันของคำแนะนำการกด / ป๊อปที่ใช้กับการลงทะเบียนในแอสเซมบลี x86 คืออะไร