Cơ chế chính xác được đưa ra ở đây, trên Linux: trong việc xử lý lỗi trang trên ánh xạ ẩn danh, bạn kiểm tra xem liệu đó có phải là "phân bổ không tăng trưởng" mà bạn nên mở rộng như một ngăn xếp hay không. Nếu bản ghi khu vực VM nói rằng bạn nên, thì bạn điều chỉnh địa chỉ bắt đầu để mở rộng ngăn xếp.
Khi xảy ra lỗi trang, tùy thuộc vào địa chỉ, nó có thể được bảo dưỡng (và lỗi được dập tắt) thông qua việc mở rộng ngăn xếp. Hành vi "phát triển xuống trên một lỗi" này đối với bộ nhớ ảo có thể được yêu cầu bởi các chương trình người dùng tùy ý với MAP_GROWSDOWN
cờ được chuyển đến tòa nhà mmap
.
Bạn cũng có thể loay hoay với cơ chế này trong một chương trình người dùng:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
int main() {
long page_size = sysconf(_SC_PAGE_SIZE);
void *mem = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_GROWSDOWN|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (MAP_FAILED == mem) {
perror("failed to create growsdown mapping");
return EXIT_FAILURE;
}
volatile char *tos = (char *) mem + page_size;
int i;
for (i = 1; i < 10 * page_size; ++i)
tos[-i] = 42;
fprintf(stderr, "inspect mappping for originally page-sized %p in /proc... press any key to continue...\n", mem);
(void) getchar();
if (munmap(mem, page_size))
perror("failed munmap");
return EXIT_SUCCESS;
}
Khi nó nhắc bạn tìm pid của chương trình (thông qua ps
) và nhìn vào /proc/$THAT_PID/maps
để xem khu vực ban đầu đã phát triển như thế nào.
ulimit -s
).